使用threeJs + dat.GUI实现一个旋转星空的效果,效果如下:
完整代码可以去
文章末尾直接拿去使用

大概步骤
通过本文的学习, 你将会收获:
这里直接写在html 里面, 引入了CDN加载. 如果在vue or react等中使用,可使用包管理器进行依赖的下载.
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>  <!-- 引入Three.js库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>  <!-- 引入dat.GUI库 -->scene。camera,设置视角、宽高比、近裁剪面和远裁剪面。renderer,设置渲染器的尺寸,并将其添加到文档的 body 中。    // 初始化场景、相机、渲染器
        const scene = new THREE.Scene();  // 创建一个新的Three.js场景
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);  // 创建透视相机
        const renderer = new THREE.WebGLRenderer();  // 创建WebGL渲染器
        renderer.setSize(window.innerWidth, window.innerHeight);  // 设置渲染器的大小为窗口的内宽和内高
        document.body.appendChild(renderer.domElement);  // 将渲染器的canvas元素添加到HTML文档中starSettings,包括颜色、大小和数量以及重置方法.       // dat.GUI配置
        const starSettings = {
            color: 0xffffff,  // 初始星星颜色为白色
            size: 1,  // 初始星星大小
            count: 1000,  // 初始星星数量
            // 重置函数
            reset: function () {
                this.color = 0xffffff;  // 重置颜色为白色
                this.size = 1;  // 重置大小为1
                this.count = 1000;  // 重置数量为1000
                updateStars();  // 更新星星 // 同步 GUI 控件的值
                guiControllers.color.setValue(this.color);
                guiControllers.size.setValue(this.size);
                guiControllers.count.setValue(this.count);
            }
        };
       const gui = new dat.GUI();  // 创建dat.GUI对象
        // 创建 GUI 控件并保存引用以便后续更新
        const guiControllers = {
            color: gui.addColor(starSettings, 'color').name('颜色').onChange(updateStars),  // 添加颜色控制
            size: gui.add(starSettings, 'size', 0.1, 10).name('大小').onChange(updateStars),  // 添加大小控制
            count: gui.add(starSettings, 'count', 100, 10000).name('数量').onChange(updateStars),  // 添加数量控制
            reset: gui.add(starSettings, 'reset').name('重置')  // 添加重置按钮
        };这里使用到的GUI的方法说明:
1. add
add(object, property, [min], [max], [step])
创建一个新的控件,并将其添加到 GUI 中。
object:包含要控制属性的对象。property:要控制的属性。min:属性的最小值(可选)。max:属性的最大值(可选)。step:属性的步长(可选)。GUIController 对象。2. addColor
addColor(object, property)
创建一个颜色选择控件,并将其添加到 GUI 中。
object:包含要控制属性的对象。property:要控制的属性。GUIController 对象。createStars 函数来创建星星。
 geometry 和一个空的顶点数组 vertices。
 starSettings.count 循环生成随机的 x、y、z 坐标,并将它们添加到 vertices 数组中。
 THREE.Float32BufferAttribute 将顶点数组添加到几何体中。
 material,并结合几何体和材质创建一个 THREE.Points 对象 stars。
  function createStars() {
            const geometry = new THREE.BufferGeometry();  // 创建几何体
            const vertices = [];  // 用于存储星星位置的数组
            for (let i = 0; i < starSettings.count; i++) {  // 根据星星数量生成顶点
                const x = THREE.MathUtils.randFloatSpread(2000);  // 随机生成x坐标
                const y = THREE.MathUtils.randFloatSpread(2000);  // 随机生成y坐标
                const z = THREE.MathUtils.randFloatSpread(2000);  // 随机生成z坐标
                vertices.push(x, y, z);  // 将生成的顶点添加到数组中
            }
            console.log(vertices); // 包含3000 个 随机顶点值的数组
            geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));  // 将顶点添加到几何体中
            console.log(geometry.getAttribute('position').count);
            const material = new THREE.PointsMaterial({ color: starSettings.color, size: starSettings.size });  // 创建星星材质
            const stars = new THREE.Points(geometry, material);  // 创建星星物体
            return stars;  // 返回创建的星星
        }
 let stars = createStars();  // 调用createStars函数创建星星
 scene.add(stars);  // 将星星添加到场景中额外说明:
调用
createStars方法后,返回的对象stars是一个包含 1000 个星星的THREE.Points对象。每个星星的位置由顶点数组中的坐标决定。
具体来说,createStars 方法中:
THREE.BufferGeometry 对象 geometry。vertices 数组,每三个元素(x, y, z)表示一个星星的位置。由于 starSettings.count 是 1000,所以会有 1000 个星星,每个星星用 3 个坐标值表示,共计 3000 个值。vertices 数组设置为 geometry 对象的 position 属性。THREE.PointsMaterial 对象 material,用于定义星星的材质。geometry 和 material 创建一个 THREE.Points 对象 stars,该对象包含了所有的星星。返回的 stars 对象中包含 1000 个星星,每个星星的位置由顶点数组定义。因此,尽管 createStars 方法返回的是一个对象,但这个对象实际上表示了 1000 个星星的位置和材质。
总体来说:
vertices 数组中包含 3000 个值,每三个值表示一个星星的 x, y, z 坐标。geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3)) 将这些坐标作为星星的位置属性添加到几何体中。new THREE.Points(geometry, material) 创建了一个包含所有星星的 THREE.Points 对象。stars 对象表示 1000 个星星。因此,返回的 stars 对象是一个包含 1000 个星星的集合。
animate 函数,用于执行动画循环。requestAnimationFrame 调用 animate 函数,确保动画持续进行。        // 动画循环
        function animate() {
            requestAnimationFrame(animate);  // 请求下一帧动画
            stars.rotation.x += 0.001;  // 旋转星星
            stars.rotation.y += 0.002;  // 旋转星星
            renderer.render(scene, camera);  // 渲染场景
        }
        animate();  // 开始动画额外说明
requestAnimationFrame 方法可以查看这个链接 developer.mozilla.org/zh-CN/docs/…
当我们调制控件某个值的大小的就会触发页面的重更新.
updateStars 函数,当用户通过 dat.GUI 修改设置时,更新星星。     function updateStars() {
            scene.remove(stars);  // 从场景中移除旧的星星
            stars = createStars();  // 创建新的星星
            scene.add(stars);  // 将新的星星添加到场景中
     }执行流程
修改值 ==> 修改starSettings中的值 ==> 触发updateStars的函数执行 ==> 删除场景 ==> 重新读取starSettings参数并创建对象 ==> 放入场景中
添加窗口调整事件监听器,当窗口大小变化时,更新相机的宽高比和渲染器的尺寸。
       // 窗口大小调整
        window.addEventListener('resize', () => {  // 监听窗口大小变化事件
            camera.aspect = window.innerWidth / window.innerHeight;  // 更新相机的宽高比
            camera.updateProjectionMatrix();  // 更新相机投影矩阵
            renderer.setSize(window.innerWidth, window.innerHeight);  // 更新渲染器大小
        });<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Three.js 星空</title>
    <style>
        body {
            margin: 0;
        }
        /* 去掉页面的默认边距 */
        canvas {
            display: block;
        }
        /* 将canvas设置为块级元素,去掉默认内边距 */
    </style>
</head>
<body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script> <!-- 引入Three.js库 -->
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script> <!-- 引入dat.GUI库 -->
    <script>
        // 初始化场景、相机、渲染器
        const scene = new THREE.Scene();  // 创建一个新的Three.js场景
        const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);  // 创建透视相机
        const renderer = new THREE.WebGLRenderer();  // 创建WebGL渲染器
        renderer.setSize(window.innerWidth, window.innerHeight);  // 设置渲染器的大小为窗口的内宽和内高
        document.body.appendChild(renderer.domElement);  // 将渲染器的canvas元素添加到HTML文档中
        // dat.GUI配置
        const starSettings = {
            color: 0xffffff,  // 初始星星颜色为白色
            size: 1,  // 初始星星大小
            count: 1000,  // 初始星星数量
            rotationSpeedX: 0.001,  // 初始星星x轴旋转速度
            rotationSpeedY: 0.002,  // 初始星星y轴旋转速度
            // 重置函数
            reset: function () {
                this.color = 0xffffff;  // 重置颜色为白色
                this.size = 1;  // 重置大小为1
                this.count = 1000;  // 重置数量为1000
                // 旋转速度
                this.rotationSpeedY = 0.002;
                this.rotationSpeedX = 0.001;
                updateStars();  // 更新星星 // 同步 GUI 控件的值
                guiControllers.color.setValue(this.color);
                guiControllers.size.setValue(this.size);
                guiControllers.count.setValue(this.count);
                guiControllers.rotationSpeedX.setValue(this.rotationSpeedX);
                guiControllers.rotationSpeedY.setValue(this.rotationSpeedY);
            }
        };
        function createStars() {
            const geometry = new THREE.BufferGeometry();  // 创建几何体
            const vertices = [];  // 用于存储星星位置的数组
            for (let i = 0; i < starSettings.count; i++) {  // 根据星星数量生成顶点
                const x = THREE.MathUtils.randFloatSpread(2000);  // 随机生成x坐标
                const y = THREE.MathUtils.randFloatSpread(2000);  // 随机生成y坐标
                const z = THREE.MathUtils.randFloatSpread(2000);  // 随机生成z坐标
                vertices.push(x, y, z);  // 将生成的顶点添加到数组中
            }
            geometry.setAttribute('position', new THREE.Float32BufferAttribute(vertices, 3));  // 将顶点添加到几何体中
    
            const material = new THREE.PointsMaterial({ color: starSettings.color, size: starSettings.size });  // 创建星星材质
            const stars = new THREE.Points(geometry, material);  // 创建星星物体
            return stars;  // 返回创建的星星
        }
        let stars = createStars();  // 调用createStars函数创建星星
        scene.add(stars);  // 将星星添加到场景中
        camera.position.z = 5;  // 设置相机位置
        // 动画循环
        function animate() {
            requestAnimationFrame(animate);  // 请求下一帧动画
            stars.rotation.x += starSettings.rotationSpeedX;  // 旋转星星
            stars.rotation.y += starSettings.rotationSpeedY;  // 旋转星星
            renderer.render(scene, camera);  // 渲染场景
        }
        animate();  // 开始动画
        const gui = new dat.GUI();  // 创建dat.GUI对象
        // 创建 GUI 控件并保存引用以便后续更新
        const guiControllers = {
            color: gui.addColor(starSettings, 'color').name('颜色').onChange(updateStars),  // 添加颜色控制
            size: gui.add(starSettings, 'size', 0.1, 10).name('大小').onChange(updateStars),  // 添加大小控制
            count: gui.add(starSettings, 'count', 100, 10000).name('数量').onChange(updateStars),  // 添加数量控制
            // 添加星星的旋转速度
            rotationSpeedX: gui.add(starSettings, 'rotationSpeedX', 0.001, 0.1, 0.001).name('旋转速度X').onChange(updateStars),
            rotationSpeedY: gui.add(starSettings, 'rotationSpeedY', 0.001, 0.1, 0.001).name('旋转速度Y').onChange(updateStars),
            reset: gui.add(starSettings, 'reset').name('重置')  // 添加重置按钮
        };
        function updateStars() {
            scene.remove(stars);  // 从场景中移除旧的星星
            stars = createStars();  // 创建新的星星
            scene.add(stars);  // 将新的星星添加到场景中
        }
        // 窗口大小调整
        window.addEventListener('resize', () => {  // 监听窗口大小变化事件
            camera.aspect = window.innerWidth / window.innerHeight;  // 更新相机的宽高比
            camera.updateProjectionMatrix();  // 更新相机投影矩阵
            renderer.setSize(window.innerWidth, window.innerHeight);  // 更新渲染器大小
        });
    </script>
</body>
</html>