使用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 相关文章推荐
Code:findPosX 和 findPosY
Dec 20 Javascript
jquery 表单取值常用代码
Dec 22 Javascript
js获取本机的外网/广域网ip地址完整源码
Aug 12 Javascript
javascript的BOM汇总
Jul 16 Javascript
在easyUI开发中,出现jquery.easyui.min.js函数库问题的解决办法
Sep 11 Javascript
jQuery中fadein与fadeout方法用法示例
Sep 16 Javascript
移动端使用localStorage缓存Js和css文的方法(web开发)
Sep 20 Javascript
js无提示关闭浏览器窗口的两种方法分析
Nov 06 Javascript
js 转义字符及URI编码详解
Feb 28 Javascript
Vue.js实战之Vuex的入门教程
Apr 01 Javascript
利用VS Code开发你的第一个AngularJS 2应用程序
Dec 15 Javascript
小程序hover-class点击态效果实现
Feb 26 Javascript
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下正则来匹配dede模板标签的代码
2010/08/21 PHP
解析PHP强制转换类型及远程管理插件的安全隐患
2014/06/30 PHP
Laravel框架中自定义模板指令总结
2017/12/17 PHP
PHP缓存工具XCache安装与使用方法详解
2018/04/09 PHP
document对象execCommand的command参数介绍
2006/08/01 Javascript
JavaScript DOM 学习第七章 表单的扩展
2010/02/19 Javascript
js数据验证集合、js email验证、js url验证、js长度验证、js数字验证等简单封装
2010/05/15 Javascript
Javascript获取HTML静态页面参数传递值示例
2013/08/18 Javascript
javascript实现验证身份证号的有效性并提示
2015/04/30 Javascript
javascript实现youku的视频代码自适应宽度
2015/05/25 Javascript
JavaScript实现仿网易通行证表单验证
2015/05/25 Javascript
Bootstrap组件系列之福利篇几款好用的组件(推荐)
2016/06/23 Javascript
js调用父框架函数与弹窗调用父页面函数的简单方法
2016/11/01 Javascript
jQuery在header中设置请求信息的方法
2017/03/06 Javascript
解决easyui日期时间框ie的兼容的问题
2018/03/01 Javascript
vuejs实现ready函数加载完之后执行某个函数的方法
2018/08/31 Javascript
如何给element添加一个抽屉组件的方法步骤
2019/07/14 Javascript
百度小程序之间的页面通信过程详解
2019/07/18 Javascript
Vue.use()在new Vue() 之前使用的原因浅析
2019/08/26 Javascript
layui动态渲染生成左侧3级菜单的方法(根据后台返回数据)
2019/09/23 Javascript
javascript如何实现create方法
2019/11/04 Javascript
[02:53]DOTA2英雄基础教程 山岭巨人小小
2013/12/09 DOTA
[52:02]DOTA2-DPC中国联赛 正赛 Phoenix vs Dragon BO3 第二场 2月26日
2021/03/11 DOTA
KMP算法精解及其Python版的代码示例
2016/06/01 Python
python数据类型_元组、字典常用操作方法(介绍)
2017/05/30 Python
python tensorflow学习之识别单张图片的实现的示例
2018/02/09 Python
Python3导入自定义模块的三种方法详解
2018/04/13 Python
python保存网页图片到本地的方法
2018/07/24 Python
Python3实现zip分卷压缩过程解析
2019/10/09 Python
实习护士自我鉴定
2013/10/13 职场文书
司马光教学反思
2014/02/01 职场文书
2014年计生标语
2014/06/23 职场文书
幼儿园小班班务总结
2015/08/03 职场文书
推普标语口号大全
2015/12/26 职场文书
理解深度学习之深度学习简介
2021/04/14 Python
SQL SERVER触发器详解
2022/02/24 SQL Server