使用Three.js实现太阳系八大行星的自转公转示例代码


Posted in Javascript onApril 09, 2019

一. Three.js框架简介

Three.js是用javascript编写的WebGL第三方库,运用three.js框架写3D程序,就如同在现实生活中观察一个3D场景一样,让人置身其中。介绍three.js必须提到它的三大组件,Scene,Camera,Render。它们是整个框架的基础,有了这三个组件才能将物体渲染到网页上,实现整个场景的搭建。

场景(scene)

顾名思义,就是用来放置所有的元素。

var scene = new THREE.Scene(); //建立场景

相机(camera)

相机,我们要在哪个位置,如何去看这些元素。

相机分为多种,不展开介绍,这里我们使用的是 透视相机。

var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000); //设置相机为 角度60度,宽高比,最近端Z轴为1,最远端Z轴为10000

我们可以通过一张来自three.js文档中的图片来了解这些属性

使用Three.js实现太阳系八大行星的自转公转示例代码

渲染器(render)

当把场景中的所有内容准备好后,就可以对场景进行渲染,表示我们怎样来绘制这些元素。

渲染器也分为多种,这里使用的是WebGLRenderer;

var renderer = new THREE.WebGLRenderer();

具体步骤:建立元素->定义相机->搭建场景->将元素和相机放入场景中->渲染场景

具体代码我们会在后面介绍,然后让我们先瞅一眼效果图。

二. 基本初始化

这里直接在CDN上引入three.js

<script src="https://cdn.bootcss.com/three.js/r83/three.min.js"></script>

注:因为某些行星的大小,转速,距离差距过大,所以进行了一些不平衡调整。

下面将一一分析这些元素是如何放入的。

1.canvas

我们没有把场景直接挂载到body中,而是在body中放置了一个canvas画布,在其上显示。

2.背景

我们没有做3D的旋转背景,而是直接放了一张背景图作为小太阳系的背景。这张背景图是直接在canvas中放置的。

<canvas id="webglcanvas"></canvas>
renderer = new THREE.WebGLRenderer({ //定义渲染器
   alpha: true, //让背景透明,默认是黑色,以显示我们自己的背景图
  });
renderer.setClearAlpha(0);
//css文件
#webglcanvas {
   background: url(./images/bg4.jpg) no-repeat;
   background-size: cover;
  }

但如果只是这样简单的操作是没有用的,因为在添加渲染器后,会默认添加一个背景颜色为黑色。所以要在渲染器中设置它的alpha属性(WebGL渲染器及属性方法),让背景透明,以显示我们自己的背景图

3.定义基本组件

定义场景

scene = new THREE.Scene(), //建立场景

定义照相机位置

camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1,10000); //设置相机为 角度60度,宽高比,最近端Z轴为1,最远端Z轴为10000
  camera.position.z = 2000; //调整相机位置
  camera.position.y = 500;

建立一个组

组可以看作是一些元素的容器,将某些有共同特征的元素放在一个组里。

group = new THREE.Group(), //建立一个组

我会在第三节解释为什么要建立额外16个组。

//下面这些组用来建立每个星球的父元素,以实现 八大行星不同速度的公转与自转
  var group1 = new THREE.Group();
   groupParent1 = new THREE.Group();
   group2 = new THREE.Group();
   groupParent2 = new THREE.Group();
   group3 = new THREE.Group();
   groupParent3 = new THREE.Group();
   group4 = new THREE.Group();
   groupParent4 = new THREE.Group();
   group5 = new THREE.Group();
   groupParent5 = new THREE.Group();
   group6 = new THREE.Group();
   groupParent6 = new THREE.Group();
   group7 = new THREE.Group();
   groupParent7 = new THREE.Group();
   group8 = new THREE.Group();
   groupParent8 = new THREE.Group();

定义渲染器

WebGLRenderer中有一个用来绘制输出的canvas对象,现在获取设置的canvas放入我们渲染器中的canvas对象中

var canvas = document.getElementById('webglcanvas'),
renderer = new THREE.WebGLRenderer({ //定义渲染器
   alpha: true, //让背景透明,默认是黑色 以显示我们自己的背景图
   canvas: canvas, //一个用来绘制输出的Canvas对象
   antialias: true //抗锯齿
  });
renderer.setSize(window.innerWidth, window.innerHeight); //设置渲染器的宽高

4.初始化函数

在这个函数中进行一系列的初始化操作。

function init() {  //用来初始化的函数
   scene.add(group); //把组都添加到场景里

   scene.add(groupParent1);
   scene.add(groupParent2);
   scene.add(groupParent3);
   scene.add(groupParent4);
   scene.add(groupParent5);
   scene.add(groupParent6);
   scene.add(groupParent7);
   scene.add(groupParent8);
   
   var loader = new THREE.TextureLoader();/*材质 纹理加载器*/
   // 太阳
   loader.load('./images/sun1.jpg', function (texture) {  
    var geometry = new THREE.SphereGeometry(250, 20, 20) //球体模型 
    var material = new THREE.MeshBasicMaterial({ map: texture }) //材质 将图片解构成THREE能理解的材质
    var mesh = new THREE.Mesh(geometry, material);  //网孔对象 第一个参数是几何模型(结构),第二参数是材料(外观)
    group.add(mesh);//添加到组里
   })
   // 水星
   loader.load('./images/water.jpg', function (texture) {
    var geometry = new THREE.SphereGeometry(25, 20, 20) //球型 
    var material = new THREE.MeshBasicMaterial({ map: texture }) //材质 将图片解构成THREE能理解的材质
    var mesh = new THREE.Mesh(geometry, material);
    group1.position.x -= 300;
    group1.add(mesh);
    groupParent1.add(group1);
   })
   //其它7颗行星参数因为太长了在这里就不给出了,但参数的设置原理都是一样的
   }

简要解释一下:

var loader = new THREE.TextureLoader();是定义了一个材质纹理加载器。

var geometry = new THREE.SphereGeometry(250, 20, 20);建立一个球体模型,球体半径为250,水平分割面的数量20,垂直分割面的数量20。

var mesh = new THREE.Mesh(geometry, material);网孔对象。

具体作用就是创建一个球体元素,先构建框架,在用行星的平面图将它包裹起来,就形成了一颗行星,再把这颗行星添加到组里,之后再把组添加到场景里。这里就构建单个元素的过程。

那么为什么太阳直接添加到组里,而水星要用两个组层级添加,且给它的位置设偏移呢。我们来到第三节。

三. 自转同时公转

旋转方式:我们要实现旋转功能有三种方式

1.旋转照相机  2.旋转整个场景(Scene)  3.旋转单个元素。

因为我们这里每个行星的自转速度,公转速度都不一样。所以设置整体旋转并不可行,所以要给每个元素设置不同的旋转属性。

旋转机制:这里介绍物体的rotation属性,相对于自身旋转。

例如:

scene.rotation.y += 0.04; //整个场景绕自身的Y轴逆时针旋转

进入正题

使用Three.js实现太阳系八大行星的自转公转示例代码

Scene中的所有元素使用rotation.y属性,默认旋转轴都为这根Y轴,因为它们初始化Y轴就是这根轴。
所以让太阳旋转直接让它的组旋转就行了group.rotation.y += 0.04;

而其它行星需要让它们围绕着太阳转,就要先给它们自身设置一个位置偏移。例如水星:group1.position.x -= 300;  而此时设置group1.rotation.y属性,它就会实现自转。因为它的Y轴位置已经改变了。

使用Three.js实现太阳系八大行星的自转公转示例代码

那么此时要想再实现公转,在这个对象中是找不到默认Y轴这根线的。所以我们给group1再设置了一个“父元素”groupParent1。groupParent1.add(group1);

当我们移动了group1时,groupParent1的位置是没有变的,自然它的Y轴也不会变,又因为groupParent1包含了group1,所以旋转groupParent1时,group1也会绕着初始的默认Y轴旋转。所以设置那么多组,是为了实现每颗行星不同的速度和公转的同时自转。

使用Three.js实现太阳系八大行星的自转公转示例代码

四. 其他实现函数

function render() {
   renderer.render(scene, camera);
   camera.lookAt(scene.position); //让相机盯着场景的位置 场景始终在中间
  }
  //设置公转
  function revolution(){
   groupParent1.rotation.y += 0.15;
   groupParent2.rotation.y += 0.065;
   groupParent3.rotation.y += 0.05;
   groupParent4.rotation.y += 0.03;
   groupParent5.rotation.y += 0.001; 
   groupParent6.rotation.y += 0.02;
   groupParent7.rotation.y += 0.0005;
   groupParent8.rotation.y += 0.003;
  }
  //设置自转
  function selfRotation(){
   group.rotation.y += 0.04;
   group1.rotation.y += 0.02;
   group2.rotation.y -= 0.005;
   group3.rotation.y += 1;
   group4.rotation.y += 1;
   group5.rotation.y += 1.5;
   group6.rotation.y += 1.5;
   group7.rotation.y -= 1.5;
   group8.rotation.y += 1.2;
  }
  function Animation() {
   render();
   selfRotation();
   revolution();
   requestAnimationFrame(Animation); 
  }

最后再调用一下 init()Animation()函数就OK了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
40个有创意的jQuery图片、内容滑动及弹出插件收藏集之一
Dec 31 Javascript
jQuery获得内容和属性方法及示例
Dec 02 Javascript
js中indexof的用法详细解析
Dec 24 Javascript
Jquery遍历checkbox获取选中项value值的方法
Feb 13 Javascript
jquery实现通用版鼠标经过淡入淡出效果
Jun 15 Javascript
jQuery判断数组是否包含了指定的元素
Mar 10 Javascript
jQuery validate插件实现ajax验证重复的2种方法
Jan 22 Javascript
JS实现标签页切换效果
May 04 Javascript
js实现左右轮播图
Jan 09 Javascript
jQuery 图片查看器插件 Viewer.js用法简单示例
Apr 04 jQuery
VUE前端从后台请求过来的数据进行转换数据结构操作
Nov 11 Javascript
vue实现图书管理系统
Dec 29 Vue.js
webpack4实现不同的导出类型
Apr 09 #Javascript
Vue中使用create-keyframe-animation与动画钩子完成复杂动画
Apr 09 #Javascript
基于three.js实现的3D粒子动效实例代码
Apr 09 #Javascript
Koa 中的错误处理解析
Apr 09 #Javascript
简单说说如何使用vue-router插件的方法
Apr 08 #Javascript
利用Bootstrap Multiselect实现下拉框多选功能
Apr 08 #Javascript
纯javascript实现选择框的全选与反选功能
Apr 08 #Javascript
You might like
php+js实现异步图片上传实例分享
2014/06/02 PHP
腾讯微博提示missing parameter errorcode 102 错误的解决方法
2014/12/22 PHP
浅谈PHP的排列组合(如输入a,b,c 输出他们的全部组合)
2017/03/14 PHP
删除PHP数组中的重复元素的实现代码
2017/04/10 PHP
thinkPHP5.0框架事务处理操作简单示例
2018/09/07 PHP
PHP项目多语言配置平台实现过程解析
2020/05/18 PHP
使用Grunt.js管理你项目的应用说明
2013/04/24 Javascript
jquery Tab效果和动态加载的简单实例
2013/12/11 Javascript
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
JS 事件绑定、事件监听、事件委托详细介绍
2016/09/28 Javascript
vue实现列表的添加点击
2016/12/29 Javascript
Vue源码学习之初始化模块init.js解析
2017/11/02 Javascript
移动端(微信等使用vConsole调试console的方法
2019/03/05 Javascript
面试题:react和vue的区别分析
2019/04/08 Javascript
js实现掷骰子小游戏
2019/10/24 Javascript
vue-property-decorator用法详解
2019/12/12 Javascript
使用python编写脚本获取手机当前应用apk的信息
2014/07/21 Python
Python随机数random模块使用指南
2016/09/09 Python
python+matplotlib绘制3D条形图实例代码
2018/01/17 Python
python利用微信公众号实现报警功能
2018/06/10 Python
Python面向对象程序设计构造函数和析构函数用法分析
2019/04/12 Python
python实现共轭梯度法
2019/07/03 Python
python 公共方法汇总解析
2019/09/16 Python
Python计算不规则图形面积算法实现解析
2019/11/22 Python
突袭HTML5之Javascript API扩展3—本地存储全新体验
2013/01/31 HTML / CSS
美国豪华时尚女性精品店:Kirna Zabête
2018/01/11 全球购物
Baracuta官方网站:Harrington夹克,G9,G4,G10等
2018/03/06 全球购物
会计应聘求职信范文
2013/12/17 职场文书
运动会通讯稿200字
2014/02/16 职场文书
新闻学专业大学生职业生涯规划范文
2014/03/02 职场文书
2014年行政助理工作总结
2014/11/19 职场文书
领导视察通讯稿
2015/07/18 职场文书
2019个人年度目标制定攻略!
2019/07/12 职场文书
Nginx域名转发https访问的实现
2021/03/31 Servers
使用python+pygame开发消消乐游戏附完整源码
2021/06/10 Python
js中Map和Set的用法及区别实例详解
2022/02/15 Javascript