6

基于threejs中秋佳节之际带你遨游星空?

 2 years ago
source link: https://blog.51cto.com/react/5666633
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基于threejs中秋佳节之际带你遨游星空?

精选 原创

海上生明月,天涯共此时。又是一年中秋时,回想上一次赏月已是那遥远的童年时光,忙碌使我们忘却了假日应有的舒缓。今天在这假期即将开始的时候,让我们用代码来过个节。

今天的主题是基于threejs画出月球环绕地球运动的效果,并增加飞跃星空的感觉,如封面图所示。

首先绘制出地球和月球,基于SphereBufferGeometry类绘制三维球体,参数如下:

参数 描述
radius 该属性定义球体的半径,默认值是50
widthSegments 该属性指定竖直方向上的分段数,段数越多,球体的表面越光滑,默认值是8,最小值是3
heightSegments 该属性指定水平方向上的分段数,段数越多,球体的表面越光滑,默认值是6,最小值是2
phiStart 该属性用来指定从x轴的什么位置开始绘制,取值范围是0到2*π,默认值0
phiLength 该属性用来指定从phiStart开始画多少,默认2*π(画整球)
thetaStart 该属性用来指定从y轴的什么位置开始绘制,取值范围是0到2*π,默认值0
thetaLength 该属性用来指定从thetaStart开始画多少,默认2*π(画整球)

首先在网上找一张地球平面图,此处只需要用到前面三个参数即可new THREE.SphereBufferGeometry(10, 50, 50),效果图如下:

基于threejs中秋佳节之际带你遨游星空?_最小值
基于threejs中秋佳节之际带你遨游星空?_javascript_02

月球图类似,只是会相对地球绘制的球体会小一些。

然后是给两个球体增加动画的效果,地球本身的自转效果,月球围绕地球环绕运动的效果。

地球自转效果比较简单,只需要不断修改地球实例的y轴的值即可。

planet.rotation.y += 0.002;

月球比较复杂,除开自转的同时还需增加一个环线运动效果,这里增加一个t值,默认为0,在动画运动函数中不断增加t值,并结合数学三角函数实现环绕效果。

moon.rotation.y -= 0.007;
moon.position.x = 15 * Math.cos(t) + 0;
moon.position.z = 20 * Math.sin(t) - 35;
t += 0.015;

最终动画的效果如下所示:

基于threejs中秋佳节之际带你遨游星空?_javascript_03

只有两个球体运动相对单调,所以再增加星空运动的轨迹提示氛围感。由于星星是不断运动飞出屏幕之外的,所以我们要有重新绘制的机制。

let lineTotal = 1000;
let linesGeometry = new THREE.BufferGeometry();
linesGeometry.setAttribute("position", new THREE.BufferAttribute(new Float32Array(6 * lineTotal), 3));
linesGeometry.setAttribute("velocity", new THREE.BufferAttribute(new Float32Array(2 * lineTotal), 1));
let l_positionAttr = linesGeometry.getAttribute("position");
let l_vertex_Array = linesGeometry.getAttribute("position").array;
let l_velocity_Array = linesGeometry.getAttribute("velocity").array;

for (let i = 0; i < lineTotal; i++) {
    let x = THREE.MathUtils.randInt(-100, 100);
    let y = THREE.MathUtils.randInt(10, 100);
    if (x < 7 && x > -7 && y < 20) x += 14;
    let z = THREE.MathUtils.randInt(0, -300);

    l_vertex_Array[6 * i + 0] = l_vertex_Array[6 * i + 3] = x;
    l_vertex_Array[6 * i + 1] = l_vertex_Array[6 * i + 4] = y;
    l_vertex_Array[6 * i + 2] = l_vertex_Array[6 * i + 5] = z;

    l_velocity_Array[2 * i] = l_velocity_Array[2 * i + 1] = 0;
}
let starsMaterial = new THREE.LineBasicMaterial({
    color: "#ffffff",
    transparent: true,
    opacity: 0.5,
    fog: false
});
let lines = new THREE.LineSegments(linesGeometry, starsMaterial);
linesGeometry.getAttribute("position").setUsage(THREE.DynamicDrawUsage);
scene.add(lines);

增加动画及重置

for (let i = 0; i < lineTotal; i++) {
    l_velocity_Array[2 * i] += 0.0049;
    l_velocity_Array[2 * i + 1] += 0.005;

    l_vertex_Array[6 * i + 2] += l_velocity_Array[2 * i];
    l_vertex_Array[6 * i + 5] += l_velocity_Array[2 * i + 1];

    if (l_vertex_Array[6 * i + 2] > 50) {
        l_vertex_Array[6 * i + 2] = l_vertex_Array[6 * i + 5] = THREE.MathUtils.randInt(-200, 10);
        l_velocity_Array[2 * i] = 0;
        l_velocity_Array[2 * i + 1] = 0;
    }
}

星空背景动画

正常的星空背景都会有一些星云,在此基础上再增加一张背景图的运动使之更加真实。星空背景本质也是一个球体,只是半径相对较大,肉眼看不出来。

const textureSphereBg = loader.load('https://xxx.jpg');
textureSphereBg.anisotropy = 16;
const geometrySphereBg = new THREE.SphereBufferGeometry(50, 32, 32);
const materialSphereBg = new THREE.MeshBasicMaterial({
    side: THREE.BackSide,
    map: textureSphereBg,
    fog: false
});
sphereBg = new THREE.Mesh(geometrySphereBg, materialSphereBg);
sphereBg.position.set(0, 50, 0);
scene.add(sphereBg); 

然后在整体的动画函数中修改不同方向的数值,使之感觉游荡在太空中的感觉。

sphereBg.rotation.x += 0.002;
sphereBg.rotation.y += 0.002;
sphereBg.rotation.z += 0.002;

整体实现功能就结束了,里面用到大量的threejs的相关API,有兴趣的同学可以去研究研究,最后的完整代码如下:

 https://code.juejin.cn/pen/7141241609026273321

 https://codepen.io/isladjan/pen/zYqLxeG

看完如果觉得有趣,记得点赞收藏起来。说不定哪天就用上啦~
最后祝大家中秋快乐,假期玩得开心~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)

  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK