今天郭先生收到评论,想要之前制作太阳系的案例,因为找不到了,于是在vue版本又制作一版太阳系,在线案例请点击博客原文(加载时间比较长,请稍等一下)。话不多说先看效果图。

图片有点多,先放三张,相比于上一个版本,这个版本制作更加细致,动画更加流畅。那么下面分析一下主要代码。

1. 先介绍一下变量

这里查了一些资料radiuses、distances、pub_rotation、self_rotation、pitchs分别为八大行星半径比、到太阳的距离比、公转比、自转比、自转轴倾角比。

radiuses: [2440, 6052, 6371, 3397, 71492, 60268, 25559, 24766],
distances: [5791, 10820, 14960, 22794, 77833, 142940, 287099, 450400],
pub_rotation: [88, 225, 365, 687, 4329, 10767, 30769, 60152],
self_rotation: [58.65, 243, 1, 1, 0.41, 0.42, 0.64, 0.65],
pitchs: [0, 177, 23, 25, 3, 27, 98, 28],
sunObj: {
radius: 60000//实际695500,为了好看太阳半径缩小了
},
moonObj: {
distance: 800, //实际90 为了好看地月距离放大了
radius: 1737,
pitchs: 5,
self_rotation: 27.25,
pub_rotation: 27.25
},
asteriodObj: {
radius: 2000,//
pub_rotation: 408
},

2. 引入星球的纹理贴图

由于星球的贴图加载比较慢,所以要在贴图加载之后,再进行后续操作。

let loader = new THREE.TextureLoader();
taiyangT = loader.load('/static/images/texture/planets/sun.jpg');
shuixingT = loader.load('/static/images/texture/planets/shuixing.jpg');
jinxingT = loader.load('/static/images/texture/planets/jinxing.jpg');
diqiuT = loader.load('/static/images/texture/planets/diqiu.jpg');
huoxingT = loader.load('/static/images/texture/planets/huoxing.jpg');
muxingT = loader.load('/static/images/texture/planets/muxing.jpg');
tuxingT = loader.load('/static/images/texture/planets/tuxing.jpg');
tianwangxingT = loader.load('/static/images/texture/planets/tianwangxing.jpg');
haiwangxingT = loader.load('/static/images/texture/planets/haiwangxing.jpg');
yueqiuT = loader.load('/static/images/texture/planets/yueqiu.jpg');
asteriodsT = loader.load('/static/images/texture/planets/asteriod.jpg');
tuxinghuanT = loader.load('/static/images/texture/planets/tuxingring.png');

3. 绘制星球,并在场景中添加

这里我们写了一个公共的方法createMesh,这个方法传两个参数贴图和索引,可以根据这个索引找到自转周期、公转周期距离等等。

shuixing = this.createMesh(shuixingT, 0);
jinxing = this.createMesh(jinxingT, 1);
diqiu = this.createMesh(diqiuT, 2);
huoxing = this.createMesh(huoxingT, 3);
muxing = this.createMesh(muxingT, 4);
tuxing = this.createMesh(tuxingT, 5);
tianwangxing = this.createMesh(tianwangxingT, 6);
haiwangxing = this.createMesh(haiwangxingT, 7);
taiyang = this.createTaiyang();
yueqiu = this.createYueqiu(); scene.add(shuixing);
scene.add(jinxing);
scene.add(diqiu);
scene.add(huoxing);
scene.add(muxing);
scene.add(tuxing);
scene.add(tianwangxing);
scene.add(haiwangxing);
scene.add(taiyang);
scene.add(yueqiu);

创建公共网格方法如下

createMesh(texture, index) {
let sphere = new THREE.SphereGeometry(this.radiuses[index] * this.radius_ratio, 60, 30);
let material = new THREE.MeshBasicMaterial({map: texture});
let mesh = new THREE.Mesh(sphere, material);
mesh.position.x = this.distance_ratio * this.distances[index];
return mesh;
}

创建太阳网格方法如下

createYueqiu() {
let sphere = new THREE.SphereGeometry(this.moonObj.radius * this.radius_ratio, 30, 20);
let material = new THREE.MeshBasicMaterial({map: yueqiuT});
let mesh = new THREE.Mesh(sphere, material);
mesh.position.x = this.distance_ratio * this.moonObj.distance;
let moon = new THREE.Object3D();
moon.position.copy(diqiu.position);
moon.add(mesh);
return moon;
}

4. 星体自转和公转

在render函数中调用自转和公转函数,控制自转的属性就是mesh.rotation。控制公转的属性就是mesh.position。这里使用欧拉角和THREE.Math方法

selfRotate() {
shuixing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[0]), Math.sqrt(1 / this.self_rotation[0]) * this.self_ratio * this.timeS, 0));
jinxing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[1]), Math.sqrt(1 / this.self_rotation[1]) * this.self_ratio * this.timeS, 0));
diqiu.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[2]), Math.sqrt(1 / this.self_rotation[2]) * this.self_ratio * this.timeS, 0));
huoxing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[3]), Math.sqrt(1 / this.self_rotation[3]) * this.self_ratio * this.timeS, 0));
muxing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[4]), Math.sqrt(1 / this.self_rotation[4]) * this.self_ratio * this.timeS, 0));
tuxing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[5]), Math.sqrt(1 / this.self_rotation[5]) * this.self_ratio * this.timeS, 0));
tianwangxing.rotation.copy(new THREE.Euler(0, Math.sqrt(1 / this.self_rotation[6]) * this.self_ratio * this.timeS, THREE.Math.degToRad(this.pitchs[6]), 'ZYX'));
haiwangxing.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.pitchs[7]), Math.sqrt(1 / this.self_rotation[7]) * this.self_ratio * this.timeS, 0));
// yueqiu.children[0].rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.moonObj.pitchs), Math.sqrt(1 / this.moonObj.self_rotation) * this.self_ratio * this.timeS, 0));
yueqiu.position.copy(diqiu.position);
yueqiu.rotation.copy(new THREE.Euler(THREE.Math.degToRad(this.moonObj.pitchs), Math.sqrt(1 / this.moonObj.self_rotation) * this.self_ratio * this.timeS, 0));
asteriods.rotation.copy(new THREE.Euler(0, this.timeS * this.pub_ratio / this.asteriodObj.pub_rotation / 2, 0));
},
pubRotate() {
shuixing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[0]) * this.distance_ratio * this.distances[0], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[0]) * this.distance_ratio * this.distances[0]);
jinxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[1]) * this.distance_ratio * this.distances[1], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[1]) * this.distance_ratio * this.distances[1]);
diqiu.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[2]) * this.distance_ratio * this.distances[2], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[2]) * this.distance_ratio * this.distances[2]);
huoxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[3]) * this.distance_ratio * this.distances[3], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[3]) * this.distance_ratio * this.distances[3]);
muxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[4]) * this.distance_ratio * this.distances[4], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[4]) * this.distance_ratio * this.distances[4]);
tuxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[5]) * this.distance_ratio * this.distances[5], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[5]) * this.distance_ratio * this.distances[5]);
tianwangxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[6]) * this.distance_ratio * this.distances[6], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[6]) * this.distance_ratio * this.distances[6]);
haiwangxing.position.set(Math.cos(this.timeP * this.pub_ratio / this.pub_rotation[7]) * this.distance_ratio * this.distances[7], 0, -Math.sin(this.timeP * this.pub_ratio / this.pub_rotation[7]) * this.distance_ratio * this.distances[7]);
}

5. 使用动画,提升逼格

这里使用了tween控制相机的position和lookat属性,实现空间穿梭的感觉。

initTween() {
let pos = {x: 0, y: 0, z: -96, lx: 0, ly: 0, lz: 0};
tween1 = new TWEEN.Tween(pos).to({x: 57.91, y: 0, z: -5, lx: 57.91, ly: 0, lz: 0}, 20 * this.animation_time);
tween1.easing(TWEEN.Easing.Linear.None);
tween2 = new TWEEN.Tween(pos).to({x: 108.2, y: 0, z: -13, lx: 108.2, ly: 0, lz: 0}, 22 * this.animation_time);
tween2.easing(TWEEN.Easing.Linear.None);
tween3 = new TWEEN.Tween(pos).to({x: 149.6, y: 0, z: -14, lx: 149.6, ly: 0, lz: 0}, 24 * this.animation_time);
tween3.easing(TWEEN.Easing.Linear.None);
tween4 = new TWEEN.Tween(pos).to({x: 227.94, y: 0, z: -6, lx: 227.94, ly: 0, lz: 0}, 27 * this.animation_time);
tween4.easing(TWEEN.Easing.Linear.None);
tween5 = new TWEEN.Tween(pos).to({x: 436.5, y: 0, z: -6, lx: 436.5, ly: 0, lz: 0}, 30 * this.animation_time);
tween5.easing(TWEEN.Easing.Linear.None);
tween6 = new TWEEN.Tween(pos).to({x: 778.33, y: 0, z: -112, lx: 778.33, ly: 0, lz: 0}, 34 * this.animation_time);
tween6.easing(TWEEN.Easing.Linear.None);
tween7 = new TWEEN.Tween(pos).to({x: 1429.4, y: 0, z: -155, lx: 1429.4, ly: 0, lz: 0}, 35 * this.animation_time);
tween7.easing(TWEEN.Easing.Linear.None);
tween8 = new TWEEN.Tween(pos).to({x: 2871, y: 0, z: -46, lx: 2871, ly: 0, lz: 0}, 36 * this.animation_time);
tween8.easing(TWEEN.Easing.Linear.None);
tween9 = new TWEEN.Tween(pos).to({x: 4504, y: 0, z: -46, lx: 4504, ly: 0, lz: 0}, 37 * this.animation_time);
tween9.easing(TWEEN.Easing.Linear.None);
tween10 = new TWEEN.Tween(pos).to({x: -600, y: 452, z: 0, lx: 778.33, ly: 0, lz: 0}, 38 * this.animation_time);
tween10.easing(TWEEN.Easing.Linear.None); tween1.chain(tween2).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show1 = false).onComplete(() => this.show2 = true);
tween2.chain(tween3).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show2 = false).onComplete(() => this.show3 = true);
tween3.chain(tween4).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show3 = false).onComplete(() => this.show4 = true);
tween4.chain(tween5).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show4 = false).onComplete(() => this.show5 = true);
tween5.chain(tween6).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show5 = false).onComplete(() => this.show6 = true);
tween6.chain(tween7).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show6 = false).onComplete(() => this.show7 = true);
tween7.chain(tween8).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show7 = false).onComplete(() => this.show8 = true);
tween8.chain(tween9).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show8 = false).onComplete(() => this.show9 = true);
tween9.chain(tween10).onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show9 = false).onComplete(() => this.show10 = true);
tween10.onUpdate(onUpdate).delay(50 * this.animation_time).onStart(() => this.show10 = false); tween1.start();
},

主要代码差不多就是这样,像这样制作太阳系并不难,只要你敢想。

转载请注明地址:郭先生的博客

three.js 郭先生制作太阳系的更多相关文章

  1. js傻瓜式制作电子时钟

    js傻瓜式制作电子时间 使用到的知识点 setInterval函数 构建函数new Date if判断 demo: //css样式请自行设置 <span id="timer" ...

  2. three.js cannon.js物理引擎制作一个保龄球游戏

    关于cannon.js我们已经学习了一些知识,今天郭先生就使用已学的cannon.js物理引擎的知识配合three基础知识来做一个保龄球小游戏,效果如下图,在线案例请点击博客原文. 我们需要掌握的技能 ...

  3. D3.js(v3)+react 制作 一个带坐标与比例尺的柱形图 (V3版本)

    现在用D3.js + react做一个带坐标轴和比例尺的柱形图.我已经尽力把代码全部注释上了,最后我也会把完整柱形图代码奉上.如果还有疑惑的,可以去翻看一下我之前介绍的方法,以下方法都有介绍到. 还有 ...

  4. Walkway.js – 用线条制作简约的 SVG 动画

    Walkway.js 是一个使用线条和路径元素组成 SVG 动画图像的简单方法.只需根据提供的配置对象创建一个新的 Walkway 实例就可以了.这种效果特别适合那些崇尚简约设计风格的网页.目前, W ...

  5. js笔记(制作一个简单的计数器)

    首先编写静态页中的按钮: <input  id="result" type="button" value="该程序已经运行了0秒!"/ ...

  6. 通过js代码来制作数据库增删改查插件

    代码流程 1.订制表头:table_config 2.订制显示内容: table_config,data_list 3.加载框: 图片,position:fixed       4.-字符串格式化   ...

  7. 利用js键盘事件制作会移动效果

    会移动的方块 描述 按键盘上的方向键方块会移动,按住alt键和方向键进行大幅度移动 <!DOCTYPE html> <html lang="en"> < ...

  8. js颜色选择器 制作分析

    给html元素设置事件监听, 触发事件 弹出颜色选择器 颜色选择器绘制 获取上次选择的颜色(当前颜色) 绘制渐变色板(canvas) (方法: 横轴渐变ff0000, ffff00, 00ff00, ...

  9. 使用JS的画布制作一个瞄准镜

    <canvas width="600" height="500" id="myCanvas"></canvas> & ...

随机推荐

  1. 2020-06-30 pol实现execl导入导出

    1.导入依赖 <!-- 解析表格 --> <dependency> <groupId>org.apache.poi</groupId> <arti ...

  2. 08 . Kubernetes之 ingress及Ingress Controller

    Ingress简介 ingress是什么? 上篇文章介绍service时有说了暴露了service的三种方式ClusterIP.NodePort与LoadBalance,这几种方式都是在service ...

  3. Oauth2.0认证流程

  4. 使用.Net Core实现的一个图形验证码

    SimpleCaptcha是一个使用简单,基于.Net Standard 2.0的图形验证码模块.它的灵感来源于Edi.Wang的这篇文章https://edi.wang/post/2018/10/1 ...

  5. 「期望」「洛谷P1297」单选错位

    题目 题目描述 gx和lc去参加noip初赛,其中有一种题型叫单项选择题,顾名思义,只有一个选项是正确答案.试卷上共有n道单选题,第i道单选题有ai个选项,这ai个选项编号是1,2,3,-,ai,每个 ...

  6. 洛谷CF1292A NEKO's Maze Game,还是思维。。。

    题目直接找链接 题意: 有一个2*n大的平面,有的格子不能走,有的格子可以走,最初状态所有格子都可以走,有q个操作,每个操作都把某个格子变化一下:能走变不能走,不能走变能走,输出每次操作之后能否从1, ...

  7. 阐述Fetch.ai的能源市场优化

    原文链接:https://fetch.ai/explaining-fetch-ais-energy-market-optimization/ 阐述Fetch.ai的能源市场优化 2019年11月4日 ...

  8. Spring-boot 启动报错 调试小技巧

    描述: 我们在启动spring-boot,spring-cloud 项目时,是不是经常 遇到报错,但是在控制台 没有能找到 具体 报错信息,只是 提示,启动失败,缺乏具体的报错信息,这样就很不方便我们 ...

  9. sublime text 3+java只编译不输出结果 solution

    文章摘自:https://blog.csdn.net/VincentLuo91/article/details/53007135 版权声明:本文为CSDN博主「vincentluo91」的原创文章,遵 ...

  10. 数据可视化之DAX篇(七) Power BI中用DAX生成的表如何添加索引列?

    ​https://zhuanlan.zhihu.com/p/74732578 来源于知识星球中一个星友的问题,使用DAX在PowerBI中新建了一个表,如何为这个表添加索引列呢? 假如数据模型中只有一 ...