前端小练习——星辰宇宙(JS没有上限!!!)

10,226次阅读
没有评论

共计 9077 个字符,预计需要花费 23 分钟才能阅读完成。

        前言:在刚开始学习前端的时候,我们会学习到前端三件套中的 JavaScript,可能那时候读者没有觉得 JavaScript 这个语言有多么的牛逼,本篇文章将会使用一个炫酷的案例来刷新你对 JavaScript 这个语言的认知与理解。


✨✨✨这里是秋刀鱼不做梦的 BLOG

✨✨✨想要了解更多内容可以访问我的主页 秋刀鱼不做梦 -CSDN 博客

先让我们看一下最终的结果:

在开始讲解这个炫酷的案例之前,先让我们了解一下本案例所需的前置知识:

  1. Three.js:一个用于创建和显示 3D 图形的 JavaScript 库。代码中导入了 Three.js 的核心库和轨道控制库(OrbitControls),用于处理 3D 场景的创建和相机控制。

  2. WebGL:用于在网页中绘制 3D 图形的底层 API。Three.js 封装了 WebGL,使得 3D 渲染变得更简单。

  3. 模块化 JavaScript:使用 ES6 的模块导入语法 (import) 引入外部库,使代码结构更加清晰。

  4. 着色器编程:自定义顶点和片段着色器,通过 onBeforeCompile 方法替换默认着色器,控制点的大小、颜色和运动效果。

  5. 缓冲几何体:使用 BufferGeometry 来管理大量点的性能,提升渲染效率。

  6. 动画循环:利用 setAnimationLoop 实现流畅的渲染动画,每帧更新控制器状态和场景渲染。

  7. 响应式设计:通过 resize 事件监听器,动态调整相机和渲染器的尺寸,以适应浏览器窗口的变化。

        ——在文章的最后,我们给出了实现这个案例的全部代码,读者可以直接复制后在自己的编译器上执行一下!!!

        那么现在正式开始我们的讲解:

目录

1. 导入库和清理控制台

2. 创建场景和相机

3. 创建渲染器

4. 处理窗口大小变化

5. 控制器设置

6. 创建全局 uniform 变量和点的属性

7. 创建点的顶点数组

 8. 添加围绕的点

9. 创建几何体和材质

10. 创建点云并添加到场景

11. 渲染循环

——全部代码


1. 导入库和清理控制台

        开始我们要先导入库和清理控制台:

import * as THREE from "https://cdn.skypack.dev/three@0.136.0"; // 导入三维模型库
import {OrbitControls} from "https://cdn.skypack.dev/three@0.136.0/examples/jsm/controls/OrbitControls"; // 导入轨道控制库
console.clear(); // 清除控制台

        注释:这部分代码导入了 Three.js 库及其轨道控制功能,并清理了控制台,以便后续输出信息更清晰。

2.创建场景和相机

        在导入库和清理控制台后,我们就需要创建场景和相机:

let scene = new THREE.Scene(); // 创建场景
scene.background = new THREE.Color(0x160016); // 设置场景背景颜色

let camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000); // 创建相机
camera.position.set(0, 4, 21); // 设置相机位置

        注释:这部分代码创建了一个场景和一个透视相机,设置了相机的位置和背景颜色,为后续的渲染准备基础环境。

3. 创建渲染器

        其后我们需要为其创建一个渲染器:

let renderer = new THREE.WebGLRenderer(); // 创建渲染器
renderer.setSize(innerWidth, innerHeight); // 设置渲染器大小
document.body.appendChild(renderer.domElement); // 把渲染器加入到页面中

        注释:这里创建了一个 WebGL 渲染器,并设置其大小为窗口的宽高,最后将渲染器的 DOM 元素添加到网页中,以显示渲染结果。

4. 处理窗口大小变化

        在创建完渲染器之后,我们需要对后续的窗口的大小的变化进行处理:

window.addEventListener("resize", event => {
    camera.aspect = innerWidth / innerHeight; // 更新相机的长宽比
    camera.updateProjectionMatrix(); // 更新相机的投影矩阵
    renderer.setSize(innerWidth, innerHeight); // 设置渲染器大小
});

        注释:这一部分代码监听窗口的大小变化,动态调整相机的长宽比和渲染器的大小,确保在窗口大小变化时,场景仍能正确显示。

5. 控制器设置

        处理完窗口大小的变化之后,我们就需要对控制器进行设置了!

let controls = new OrbitControls(camera, renderer.domElement); // 创建控制器
controls.enableDamping = true; // 开启阻尼效果
controls.enablePan; // 禁用平移(此行未完成)

        注释:这部分代码创建了一个轨道控制器,允许用户通过鼠标控制相机旋转和缩放,增强用户交互体验。注意,这里 enablePan 需要完整设置。

6. 创建全局 uniform 变量和点的属性

        接下来让哦我们对全局的 uniform 变量和点的属性进行设置:

let gu = {time: { value: 0}
}; // 创建全局 uniform 变量

let sizes = []; // 点的大小数组
let shift = []; // 点的移动数组

let pushShift = () => { // 创建移动函数
    shift.push(Math.random() * Math.PI,
        Math.random() * Math.PI * 2,
        (Math.random() * 0.9 + 0.1) * Math.PI * 0.1,
        Math.random() * 0.9 + 0.1); // 随机生成位置信息
};

        注释:定义了一个全局 uniform 变量 gu 用于时间控制,并初始化了两个数组 sizesshift 用于存储点的大小和位置信息。同时,定义了一个函数 pushShift,用于生成随机的位移数据。

7. 创建点的顶点数组

        接下来让我们创建点的顶点数组:

let pts = new Array(50000).fill().map(p => {sizes.push(Math.random() * 1.5 + 0.5); // 添加随机大小
    pushShift(); // 添加位置信息
    return new THREE.Vector3().randomDirection().multiplyScalar(Math.random() * 0.5 + 9.5); // 返回随机方向的点
});

        注释:这里创建了一个包含 5 万个点的数组 pts,每个点都有随机的大小和方向。通过 randomDirection() 方法生成随机方向的向量,模拟球体内的点。

 8. 添加围绕的点

        创建完点的顶点数组之后,让我们添加其围绕的点:     

for (let i = 0; i 

        注释:这部分代码在已有的点基础上,再添加 10 万个点。使用极坐标系生成点,使其在一定范围内均匀分布,丰富了场景中的点的数量和分布。

9. 创建几何体和材质

        接下来让我们设置一下几何体和其材质样式:

let g = new THREE.BufferGeometry().setFromPoints(pts); // 创建几何体
g.setAttribute("sizes", new THREE.Float32BufferAttribute(sizes, 1)); // 设置 sizes 属性
g.setAttribute("shift", new THREE.Float32BufferAttribute(shift, 4)); // 设置 shift 属性

let m = new THREE.PointsMaterial({ // 创建点材质
    size: 0.125, // 点的大小
    transparent: true, // 透明材质
    depthTest: false, // 禁用深度测试
    blending: THREE.AdditiveBlending, // 添加混合模式
    onBeforeCompile: shader => { // 自定义着色器
        shader.uniforms.time = gu.time; // 设置 uniform 变量
        shader.vertexShader = `
            uniform float time;
            attribute float sizes;
            attribute vec4 shift;
            varying vec3 vColor;
            ${shader.vertexShader}
        `; // 修改顶点着色器

        // 更新点的大小、颜色和移动逻辑
        shader.vertexShader = shader.vertexShader
            .replace(`gl_PointSize = size;`, `gl_PointSize = size * sizes;`)
            .replace(`#include `, `#include  float d = length(abs(position)/vec3(40.,10.,40)); d=clamp(d,0.,1.); vColor = mix(vec3(227.,155.,0.),vec3(100.,50.,255.),d)/255.;`)
            .replace(`#include `, `#include  float t = time; float moveT = mod(shift.x + shift.z * t,PI2); float moveS = mod(shift.y + shift.z * t,PI2); transformed += vec3(cos(moveS) * sin(moveT), cos(moveT), sin(moveS) * sin(moveT)) * shift.w;`);
        
        // 修改片元着色器
        shader.fragmentShader = `
            varying vec3 vColor;
            ${shader.fragmentShader}
        `.replace(`#include `, `#include  float d = length(gl_PointCoord.xy - 0.5);`)
          .replace(`vec4 diffuseColor = vec4( diffuse, opacity);`, `vec4 diffuseColor = vec4(vColor, smoothstep(0.5, 0.1, d));`);
    }
});

        注释:在这部分代码中,创建了一个缓冲几何体并设置了点的大小和移动信息。还定义了一个点材质,使用自定义着色器来控制点的大小、颜色和移动效果,提供了动态的视觉效果。

10. 创建点云并添加到场景

        接下来让我们创建点云并添加到场景:

let p = new THREE.Points(g, m); // 创建点云
p.rotation.order = "ZYX"; // 设置旋转顺序
p.rotation.z = 0.2; // 设置初始旋转角度
scene.add(p); // 将点云添加到场景中

        注释:这里将创建的几何体和材质结合成一个点云对象,并设置其旋转顺序和初始旋转角度,最后将其添加到场景中以进行渲染。

11. 渲染循环

        最后让我们渲染一下环境:

let clock = new THREE.Clock(); // 创建时钟对象
renderer.setAnimationLoop(() => { // 设置渲染循环
    controls.update(); // 更新控制器
    let t = clock.getElapsedTime() * 0.5; // 获取流逝时间
    gu.time.value = t * Math.PI; // 更新时间
    p.rotation.y = t * 0.05; // 更新点云的旋转角度
    renderer.render(scene, camera); // 渲染场景和相机
});

        注释:最后,这段代码设置了渲染循环,利用时钟对象控制动画的时间,并不断更新控制器和点云的旋转,最终渲染场景。

        通过上述的分层讲解之后,我们就大致的了解每一步都是如何操作并且为什么这么操作的了,为了使读者能更好的理解上述流程,这里我们在进行总结一下:

  1. 导入库

  2. 场景和相机设置

  3. 渲染器初始化

  4. 窗口大小自适应

  5. 控制器设置

  6. 全局变量和点属性初始化

  7. 点的生成

  8. 几何体和材质设置

  9. 点云创建和添加到场景

  10. 渲染循环

        ——至此,我们就讲解完了上述案例的所以步骤了!!!

——全部代码

        最后在让我们看一下最终的效果,(JavaScript 没有极限!!!)





    
    
    
    秋刀鱼不做梦
    



    



以上就是本篇文章的全部内容了!!!

原文地址: 前端小练习——星辰宇宙(JS 没有上限!!!)

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于2024-11-10发表,共计9077字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)