耗时 2 小时!我复刻了全网超火的通透 3D 水晶球动效,Vue3+Three.js 做出高级视觉特效

之前做的3D文本效果# 别再写死静态文字了!Vue3+Three.js 实现超酷3D流光旋转文字科技感拉满!【附完整源码】有兄弟表示效果太单一,其实那个效果能做的非常炫酷。

核心就是材质上要把握好,重点其实不在技术,而在调色

简单搞一个3D的水晶球弹跳效果,具备一定的物理效果。

需求实现

球体效果相对比较简单,直接使用SphereGeometry创建即可。

主要是重力弹跳的物理效果实现起来比较麻烦,落地回弹的效果通过控制球体高度的正负实现。

另外就是阴影部分,阴影跟随球体的高度进行变化。

最后就是旋转视角和窗口自适应,还是用OrbitControlswindow.resize实现。

物体实现代码

灯光部分拆分成三个部分:环境光、平行光、点光源。

js 复制代码
function addLights() {
    // 环境光:照亮整个场景,无阴影
    const ambient = new THREE.AmbientLight(0xffffff, 0.4)
    scene.add(ambient)

    // 平行光:太阳光效果,能投射阴影
    const dirLight = new THREE.DirectionalLight(0xffffff, 1.3)
    dirLight.position.set(4, 6, 3)    // 光源位置
    dirLight.castShadow = true        // 开启投影
    dirLight.shadow.mapSize.set(2048, 2048) // 阴影清晰度
    dirLight.shadow.radius = 10       // 阴影柔和度
    scene.add(dirLight)

    // 蓝色氛围点光源
    const blueLight = new THREE.PointLight(0x639bff, 1.6, 12)
    blueLight.position.set(-5, 3, 4)
    scene.add(blueLight)

    // 紫色氛围点光源
    const purpleLight = new THREE.PointLight(0xc563ff, 1.4, 12)
    purpleLight.position.set(5, -1, 4)
    scene.add(purpleLight)
}

但是只有光,没有地面无法正常显示物体在光下的投影,所以需要增加地面。

js 复制代码
function createGround() {
    const geo = new THREE.PlaneGeometry(25, 25) // 地面大小
    const mat = new THREE.MeshStandardMaterial({
        color: 0x1e2238,    // 地面颜色
        roughness: 0.75,    // 粗糙度
        metalness: 0.05    // 金属感
    })
    ground = new THREE.Mesh(geo, mat)
    ground.rotation.x = -Math.PI / 2  // 平放地面
    ground.position.y = groundHeight  // 地面位置
    ground.receiveShadow = true       // 允许接收阴影
    scene.add(ground)
}

除此之外就是创建水晶球了,这部分直接使用SphereGeometry创建球体。

然后用MeshPhysicalMaterial增加相应的材质即可。

js 复制代码
function createCrystalBall() {
    // 球体几何体(半径,横向分段,纵向分段)
    const geo = new THREE.SphereGeometry(1, 128, 128)

    // 水晶/玻璃材质(超通透质感)
    const mat = new THREE.MeshPhysicalMaterial({
        color: 0xffffff,        // 基础颜色
        transparent: true,      // 开启透明
        transmission: 0.95,     // 透光率(1=完全透明)
        opacity: 1,            // 不透明度
        roughness: 0,          // 表面光滑度(0=镜面)
        metalness: 0,          // 金属感
        ior: 1.58,             // 折射率(水晶标准值)
        thickness: 1.8,        // 物体厚度
        envMapIntensity: 2.2,  // 环境光反射强度
        clearcoat: 1,          // 表面清漆(更亮)
        clearcoatRoughness: 0  // 清漆光滑度
    })

    ball = new THREE.Mesh(geo, mat)
    ball.castShadow = true    // 允许投射阴影
    ball.receiveShadow = true // 允许接收阴影
    ball.position.y = 3       // 初始高度(从空中落下)
    scene.add(ball)
}

物理弹跳效果

核心代码是通过控制小球的高度变化,实现弹跳效果。

通过控制其下落的速度不断增加,实现重力加速效果。

落地碰撞主要是通过检测小球高度和地面高度,当相等的时候,就认为已经落地了。

js 复制代码
unction updateBallBounce() {
    // 1. 重力效果:速度不断增加
    velocity += gravity

    // 2. 根据速度更新小球 Y 轴位置
    ball.position.y += velocity

    // 3. 落地碰撞检测 + 回弹
    // 小球最低位置 = 地面高度 + 小球半径(防止陷进地里)
    const minHeight = groundHeight + ballRadius
    if (ball.position.y <= minHeight) {
        ball.position.y = minHeight // 重置位置
        velocity = -velocity * bounce // 反向速度 × 弹性(回弹)
    }

    // 4. 小球自动旋转
    ball.rotation.y += 0.005

    // 5. 阴影同步效果:
    // 跳得越高 → 越小越淡
    // 离地面越近 → 越大越浓
    const height = ball.position.y - minHeight
    const shadowScale = THREE.MathUtils.clamp(1.2 - height * 0.15, 0.5, 1.2)
    ball.scale.set(shadowScale, shadowScale, shadowScale)
}

总结

其实场景的搭建非常简单,鼠标操作也是用的封装好的东西。

重点是在物理弹跳效果上,通过控制速度,间接控制小球的高度。

以及小球高度与地面高度的对比实现落地反弹效果。

还有就是模拟真实世界的重力衰减效果,随着不断地反弹落地,最终小球高度完全等于地面高度。

相关推荐
郭老二29 分钟前
【前端】vue3:编译步骤
前端
不在逃避q1 小时前
Trae/Vs Code/Cursor命令行无法跑npm命令
前端·arcgis·npm
夏殇之殁2 小时前
包中创建自定义列表项。 . 使用自定义列表项进行数据绑定 . 将天气预报数据保存到本地内存表,通过LiveBindings进行显示。 ...
服务器·前端·javascript
The Chosen One9852 小时前
高进度算法模板速记(待完善)
java·前端·算法
陈随易2 小时前
MoonBit抓包模块pcap,查看电脑的每一次联网通信
前端·后端·程序员
新中地GIS开发老师3 小时前
WebGIS开发学生作品|低空航天管理与航线规划系统
前端·javascript·webgis·三维gis开发
用户059540174463 小时前
大模型对话记忆持久化踩坑实录:用 Playwright 自动化测了 300 次,终于揪出会话丢失的真凶
前端·css
丙氨酸長鏈3 小时前
Web前端入门第 问:JavaScript 一个简单的 IndexedDB 数据库入门示例
前端·javascript·数据库
kyriewen4 小时前
面试官让我手写虚拟列表——AI生成的版本,快速滚动几下就白屏了
前端·javascript·面试
IT_陈寒4 小时前
Vite热更新失效?你可能漏了这个配置
前端·人工智能·后端