今天郭先生收到评论,想要之前制作太阳系的案例,因为找不到了,于是在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. P2136 拉近距离

    我也想有这样的爱情故事,可惜我单身 其实这道题就是一个比较裸的最短路问题.对于一个三元组 (S,W,T) ,S其实就是一个端点,而W就是到达的端点,连接两个端点的边长为-T,注意要取一个相反数,这样才 ...

  2. .gitkeep文件

    git 默认不会对空文件夹进行追踪: 但某些项目某些文件夹对整体框架是必不可少的,就算是空也得有: 怎么办呢?在这个文件夹下添加一个[.gitkeep]文件,这样就可以同步该文件夹了. (完)

  3. 使用 Docker 开发 - 使用多阶段构建镜像

    多阶段构建是一个新特性,需要 Docker 17.05 或更高版本的守护进程和客户端.对于那些努力优化 Dockerfiles 并使其易于阅读和维护的人来说,多阶段构建非常有用. 在多阶段构建之前 构 ...

  4. 相邻元素之间的margin合并问题

    任何元素都可以设置border 设置宽高可能无效 行内元素设置padding,margin上下是无效的,左右是有效的 外边距合并:指的是,当两个垂直外边距相遇时,它们将形成一个外边距. 合并后的外边距 ...

  5. 洛谷P3295 [SCOI2016]萌萌哒 题解

    洛谷P3295 [SCOI2016]萌萌哒 题目描述 公式粘过来就乱了,还是去洛谷看题吧 分析 如果暴力解决的话就是使用并查集把位数相同的数位并在一起.比如区间[1,2]和区间[3,4]的数字完全相同 ...

  6. 云开发 VSCode 插件 Cloudbase Toolkit 的正确打开方式

    什么是 Cloudbase Toolkit Tencent CloudBase Toolkit 是云开发的 VS Code(Visual Studio Code)插件.该插件可以让您更好地在本地进行云 ...

  7. Vue中computed的本质及与methods的区别

    一.computed的本质? computed为什么不像methods一样加小括号使用? 正常使用computed方式 运行结果 至于为什么computed为什么不像methods一样使用小括号调用, ...

  8. django中的懒加载机制

    懒加载在前端中的意义: 懒加载的主要目的就是作为服务器前端的优化,减少请求次数或者延迟请求数. 实现原理: 先加载一部分数据,当触发某个条件时利用异步加载剩余的数据,新得到的数据不会影响原有数据的显示 ...

  9. 【python接口自动化】01-requests请求

    requests是模拟HTTP.https请求接口. 一.HTTP协议介绍 1.1HTTP协议特点 1.2HTTP协议组成 请求方法 主要的请求方法有:GET.POST.DELETE .PUT .HE ...

  10. YAML 语言教程与使用案例

    YAML语言教程与使用案例,如何编与读懂写YAML文件. YAML概要 YAML 是 “YAML Ain’t a Markup Language”(YAML 不是一种标记语言)的递归缩写.在开发的这种 ...