使用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了。

总结

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

(0)

相关推荐

  • three.js绘制地球、飞机与轨迹的效果示例

    对于three.js不太熟悉的朋友们可以参考这篇文章,threejs官网:https://threejs.org/ 首先我们来看下要实现的效果 这个缩小后的图片,下面我们来看下近距离的动态效果.. 效果比较简陋,需要后期再处理... 下面进入主题,代码篇.. HTML部分: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title&

  • Three.js如何用轨迹球插件(trackball)增加对模型的交互功能详解

    前言 之前我们已经简单的给大家介绍了关于three.js入门的一些案例,下面本文将详细介绍关于Three.js如何用轨迹球插件(trackball)增加对模型的交互功能,下面话不多说了,来一起看看详细的介绍吧. 这是three.js的一个组件,需要额外的引入文件,文件的地址是在官方下载的案例examples/js/controls/TrackballControls.js. 只需要和案例里面一样设置相关的属性,并在实例化的时候讲相机传入.就可以实现交互效果. 可以实现的效果: 鼠标按住左键可以旋

  • three.js实现围绕某物体旋转

    话不多说,请看代码: 可以拖动右上角观察变化 <!DOCTYPE html> <html lang="en" style="width: 100%; height:100%;"> <head> <meta charset="UTF-8"> <title>Document</title> <script src="http://cdn.bootcss.com/t

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

    一. Three.js框架简介 Three.js是用javascript编写的WebGL第三方库,运用three.js框架写3D程序,就如同在现实生活中观察一个3D场景一样,让人置身其中.介绍three.js必须提到它的三大组件,Scene,Camera,Render.它们是整个框架的基础,有了这三个组件才能将物体渲染到网页上,实现整个场景的搭建. 场景(scene) 顾名思义,就是用来放置所有的元素. var scene = new THREE.Scene(); //建立场景 相机(camer

  • 原生js实现移动端触摸轮播的示例代码

    PC端上实现图片轮播效果很简单,只要通过使用click事件就可以非常简单的实现效果,但是在移动端上,就要通过核心的touch事件来实现. 下面是移动端手指滑动轮播图的完整代码. <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, user-scala

  • p5.js实现斐波那契螺旋的示例代码

    本篇文章主要介绍了p5.js实现斐波那契螺旋的示例代码,分享给大家,也给自己做个笔记 效果如下: 主要方法 translate() rotate() arc() 斐波那契螺旋 斐波那契螺旋线也称"黄金螺旋",是根据斐波那契数列画出来的螺旋曲线,以斐波那契数为边的正方形中画一个90度的扇形,连起来的弧线就是斐波那契螺旋. 草图 过程分解 一.定义一个空的斐波那契数组: var Fibonacci = []; 二.初始化 默认情况下draw()函数会无限重复绘图, frameRate()函

  • Js逆向实现滑动验证码图片还原的示例代码

    本文列举两个例子:某象和某验的滑动验证 一.某验:aHR0cHM6Ly93d3cuZ2VldGVzdC5jb20vZGVtby9zbGlkZS1mbG9hdC5odG1s 未还原图像: 还原后的图: 从服务端请求来的图片是打乱后的,给用户看的时候是完整的,这个过程肯定是运行了某段js代码,将打乱的图片进行还原操作.所以我们需要找到这段js,然后还原它的代码逻辑,实现图片的还原操作,找到缺口距离,实现滑动操作. 如果你仔细观察的话,你会发现还原后的图它是canvas生成出来的 那你应该会想到,那段

  • 原生JS利用transform实现banner的无限滚动示例代码

    功能 默认情况无限循环向右移动 点击数字切换到对应图片 点击左右切换可切换图片 原理 首先说下原理. 在布局上所有的图片都是重叠的,即只要保证Y方向对齐即可,当前可见的图z-index层级最高. 每隔3s中更换一张图片,使用setTimeout定时. 使用gIndex记录当前可视区域的展示的是哪张图片下标,每次更换,计算下一张图片的下标. 通过requestAnimationFrame实现一次图片切换的动画. 这种方法也可以做到整个页面始终只有2个img标签,而不必把所有的img节点全部创建出来

  • JS相册图片抖动放大展示效果的示例代码

    上篇文章给大家介绍了JS实现简单抖动效果,感兴趣的朋友点击查看. 今天给大家分享JS相册图片抖动放大展示效果,效果图如下所示: var xm; var ym; /* ==== onmousemove event ==== */ document.onmousemove = function(e){ if(window.event) e=window.event; xm = (e.x || e.clientX); ym = (e.y || e.clientY); } /* ==== window

  • three.js 实现露珠滴落动画效果的示例代码

    前言 大家好,这里是 CSS 魔法使--alphardex. 本文我们将用three.js来实现一种很酷的光学效果--露珠滴落.我们知道,在露珠从一个物体表面滴落的时候,会产生一种粘着的效果.2D平面中,这种粘着效果其实用css滤镜就可以轻松实现.但是到了3D世界,就没那么简单了,这时我们就得依靠光照来实现,其中涉及到了一个关键算法--光线步进(Ray Marching).以下是最终实现的效果图 撒,哈吉马路由! 准备工作 笔者的 three.js模板 :点击右下角的fork即可复制一份 正片

  • 基于JS实现二维码名片生成的示例代码

    目录 演示 技术栈 源码 css js 演示 技术栈 这里用到了一个二维码生成库qrcode.js下面是简单介绍: //初始化QRCode对象 var qrcode = new QRCode(document.getElementById("qrcode")); //也可以在初始化QRCode对象,传入更多参数 var qrcode = new QRCode(document.getElementById("qrcode"),{ width: 128, height

  • 基于JS编写开心消消乐游戏的示例代码

    目录 展示 游戏背景 游戏规则 源码部分 对关卡的地图设置 介绍一下游戏中的一些功能 展示 游戏背景 一天晚上,天空中掉下一颗神奇的豌豆种子,正好落在了梦之森林的村长屋附近,种子落地后吸收了池塘的水分,迅速成长,一夜之间变成参天大藤蔓…… 第二天早上,村民们醒来后看到巨大的藤蔓都惊呆了,聚在一起议论纷纷.有人说他似乎看到村长的房子在高耸入云的藤蔓上,房子似乎还在上升,有人号召说应该爬上去救村长,玩家需要爬到藤曼顶部救出村长 游戏规则 把三个颜色相同的小动物连成一条直线,即可消除.达到指定的目标通

  • JS实现别踩白块游戏的示例代码

    目录 实现思路 核心代码 HTML代码 CSS代码 JS代码 实现思路 1.offsetTop,与style.top 2.我们看到的是白块在向下运动,其实不是,政治运动的是装着白块的盒子,白块只是被装在了盒子里面被带着向下,而向下运动也只是改变top值.同事盒子total的高度也不是无限长的能一直向下运动,所以肯定是运动到某个地方他又回去了. childNodes:由childNodes属性返回的数组中包含着所有类型的节点,所有的属性节点和文本节点也包含在其中.(不能乱用) JS获取元素的lef

随机推荐