之前做的3D文本效果# 别再写死静态文字了!Vue3+Three.js 实现超酷3D流光旋转文字科技感拉满!【附完整源码】有兄弟表示效果太单一,其实那个效果能做的非常炫酷。
核心就是材质上要把握好,重点其实不在技术,而在调色。
简单搞一个3D的水晶球弹跳效果,具备一定的物理效果。

需求实现
球体效果相对比较简单,直接使用SphereGeometry创建即可。
主要是重力弹跳的物理效果实现起来比较麻烦,落地回弹的效果通过控制球体高度的正负实现。
另外就是阴影部分,阴影跟随球体的高度进行变化。
最后就是旋转视角和窗口自适应,还是用OrbitControls和window.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)
}
总结
其实场景的搭建非常简单,鼠标操作也是用的封装好的东西。
重点是在物理弹跳效果上,通过控制速度,间接控制小球的高度。
以及小球高度与地面高度的对比实现落地反弹效果。
还有就是模拟真实世界的重力衰减效果,随着不断地反弹落地,最终小球高度完全等于地面高度。