使用Three.js实现太阳系八大行星的自转公转示例代码
一. 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文档中的图片来了解这些属性
渲染器(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轴逆时针旋转
进入正题
scene中的所有元素使用rotation.y属性,默认旋转轴都为这根y轴,因为它们初始化y轴就是这根轴。
所以让太阳旋转直接让它的组旋转就行了group.rotation.y += 0.04;
而其它行星需要让它们围绕着太阳转,就要先给它们自身设置一个位置偏移。例如水星:group1.position.x -= 300; 而此时设置group1.rotation.y
属性,它就会实现自转。因为它的y轴位置已经改变了。
那么此时要想再实现公转,在这个对象中是找不到默认y轴这根线的。所以我们给group1再设置了一个“父元素”groupparent1。groupparent1.add(group1);
当我们移动了group1时,groupparent1的位置是没有变的,自然它的y轴也不会变,又因为groupparent1包含了group1,所以旋转groupparent1时,group1也会绕着初始的默认y轴旋转。所以设置那么多组,是为了实现每颗行星不同的速度和公转的同时自转。
四. 其他实现函数
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了。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
上一篇: MAYA白模渲染的方法和一些技巧介绍