头图

The bright moon is born on the sea, and the end of the world is at this time. It's the Mid-Autumn Festival again, recalling that the last time we admired the moon was the distant childhood time, and the busyness made us forget the relaxation that the holiday should have. Today as the holidays are about to start, let's celebrate the holidays with code.

Today's theme is to draw the effect of the moon's movement around the earth based on threejs, and increase the feeling of leaping over the starry sky, as shown in the cover image.

sphere drawing

First draw the earth and moon, and draw a three-dimensional sphere based on the SphereBufferGeometry class. The parameters are as follows:

parameter describe
radius This property defines the radius of the sphere, the default value is 50
widthSegments This property specifies the number of segments in the vertical direction. The more segments, the smoother the surface of the sphere. The default value is 8, and the minimum value is 3
heightSegments This property specifies the number of segments in the horizontal direction. The more segments, the smoother the surface of the sphere. The default value is 6 and the minimum value is 2
phiStart This property is used to specify where to start drawing on the x-axis, the value range is 0 to 2*π, the default value is 0
phiLength This property is used to specify how much to draw from phiStart, the default is 2*π (the whole ball is drawn)
thetaStart This property is used to specify where to start drawing on the y-axis, the value range is 0 to 2*π, the default value is 0
thetaLength This property is used to specify how much to draw from thetaStart, the default is 2*π (the whole ball is drawn)

First, find a plan of the earth on the Internet. Here you only need to use the first three parameters new THREE.SphereBufferGeometry(10, 50, 50) . The effect is as follows:

The moon map is similar, but it will be smaller than the sphere drawn by the earth.

Sphere animation

Then there is the effect of adding animation to the two spheres, the effect of the rotation of the earth itself, and the effect of the moon orbiting the earth.

The effect of the earth's rotation is relatively simple, and it is only necessary to continuously modify the value of the y-axis of the earth instance.

 planet.rotation.y += 0.002;

The moon is more complicated. In addition to the rotation, a loop motion effect needs to be added. Here, a t value is added, which is 0 by default. The t value is continuously increased in the animation motion function, and the surrounding effect is realized by combining mathematical trigonometric functions.

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

The final animation looks like this:

star trail

Only the motion of the two spheres is relatively monotonous, so the trajectory of the star movement is added to prompt the atmosphere. Since the stars are constantly moving off the screen, we need a repainting mechanism.

draw the stars

 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);

Add animation and reset

 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;
    }
}

Starry sky background animation

The normal starry sky background will have some nebulae, and on this basis, add the movement of a background image to make it more realistic. The starry sky background is also a sphere in essence, but the radius is relatively large and cannot be seen by the naked eye.

 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);

Then modify the values in different directions in the overall animation function to make it feel like wandering in space.

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

at last

The overall implementation function is over. A large number of threejs related APIs are used in it. Interested students can study and study. The final complete code is as follows:

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

refer to

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

If you find it interesting after reading it, remember to like it and bookmark it. I might use it someday~
Finally, I wish everyone a happy Mid-Autumn Festival and have a good time during the holiday~

Focus on front-end development, share dry goods related to front-end technology, public account: Nancheng Front-end (ID: nanchengfe)


南城FE
2.2k 声望574 粉丝