🌌 Three.js 滚动条 3D 视差动画原理教学:滚着滚着,就进了宇宙
风格:硬核技术 + 一点点文学幻想 + 探险日志风格
技术栈:JavaScript(主力)、Three.js(主角)、HTML/CSS(配角)
🌠 前言:滚动条不只是滚动,它是时间的流动,是空间的扭曲
在现代网页中,用户滚动页面的动作不仅能驱动页面滑动,更能驱动三维世界发生剧烈变化 。这种看似炫酷的"视差滚动",其实是一个三维视角+位移映射的魔术表演。
我们今天就来拆解这个魔术的底牌,带你一步步从 JavaScript 到 GPU,从 DOM 到 3D 空间,掌握 Three.js 中如何优雅地做出滚动驱动的视差动画。
🎢 什么是 3D 视差动画(Parallax Scrolling)
视差(Parallax)最初是天文学里的词,用来观测恒星位置随地球公转而变化的"假象"。
在前端界中,视差效果就是:背景和前景以不同速度滚动,营造出深度感和空间层次感。
🚀 进入 Three.js,我们能将页面滚动与摄像机、物体的三维坐标绑定,实现一种**"滚动中穿越空间"**的沉浸感。
🧱 核心原理拆解:把页面滚动转成三维动画
🧭 第一步:获取滚动进度
HTML 页面滚动其实就是一个"从 0 到 1"的比例尺(类似进度条)。
js
const scrollY = window.scrollY
const scrollProgress = scrollY / (document.body.scrollHeight - window.innerHeight)
你可以把这个 scrollProgress
想象成:
👨🚀 "我已经从地球滚到了火星旅程的 % 完成度"
🎥 第二步:把滚动进度映射到 Three.js 场景中
🌍 场景初始构建
javascript
import * as THREE from 'three'
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
camera.position.z = 5
const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
🧊 加几个物体(让你有东西能"穿越")
csharp
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshNormalMaterial()
const cube = new THREE.Mesh(geometry, material)
scene.add(cube)
📈 滚动进度映射到物体位置 or 摄像机位置
scss
function animate() {
requestAnimationFrame(animate)
const scrollY = window.scrollY
const scrollProgress = scrollY / (document.body.scrollHeight - window.innerHeight)
// 方法一:移动物体(你飞过去)
cube.position.z = -10 * scrollProgress
// 方法二:移动摄像机(宇宙推着你飞)
// camera.position.z = 5 + scrollProgress * 20
renderer.render(scene, camera)
}
animate()
🚨 注意:如果你移动的是摄像机,整个宇宙会随之"透视变化",那是一种更加震撼的视差效果。
🧠 数学底层揭秘:为什么会产生"深度感"?
- 摄像机离一个物体越近,它变化得越快(比如你坐高铁看路边的电线杆 vs 远山)
- 所以,只要让不同的物体(或者摄像机)以非线性速度响应滚动,就能模拟这种深度层叠
通俗理解如下:
层级 | 滚动响应速度 | 显示效果 |
---|---|---|
背景背景背景 | 慢 | 稳如泰山(远) |
中景 | 正常 | 跟着动(普通) |
前景 | 快 | 呼啸而过(近) |
🪄 Bonus:滚动驱动的动画过渡(补间神器)
你也可以用 Tween.js 或者直接用 gsap
这种神器来插值动画:
javascript
import gsap from 'gsap'
window.addEventListener('scroll', () => {
const progress = window.scrollY / (document.body.scrollHeight - window.innerHeight)
gsap.to(cube.position, {
z: -progress * 10,
duration: 0.5,
ease: 'power2.out'
})
})
这样滚动就不突兀了,而是有丝滑的物理缓动感,像滑雪一样优雅入弯~
🏔️ 场景复杂化:多图层视差世界
在真正的页面中,你可以:
- 添加多个物体,每个绑定不同的滚动速度
- 控制材质透明度、缩放、旋转,让动画更具空间幻觉
- 甚至结合 HTML + WebGL overlay,打造页面 + 3D 场景联动
ini
// 三个立方体,各自不同的滚动速率
cube1.position.z = -scrollProgress * 5
cube2.position.z = -scrollProgress * 10
cube3.position.z = -scrollProgress * 20
🌌 小提示:配合
IntersectionObserver
还能做到"到达某一段内容,触发动画"
🪐 总结:滚动,是与空间的对话
滚动条早已不是古早网页里的"拖动页面"工具,而是动画引擎的动力源泉 。
在 Three.js 的加持下,你拥有了穿越星系、折叠维度的能力。
你只是轻轻一滚,整个三维世界就开始演奏交响曲。
📚 延伸阅读推荐
🚀 愿你用 Three.js 打开 Web 的第四维度,滚着滚着就能看见银河尽头的自己。