Three.js 滚动条 3D 视差动画原理解析

🌌 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 的第四维度,滚着滚着就能看见银河尽头的自己。

相关推荐
唐璜Taro39 分钟前
electron自定义国内镜像
前端·javascript·electron
bilupilu40 分钟前
electron 静默安装同时安装完成后自动启动(nsis)
前端·javascript·electron
gnip5 小时前
首页加载、白屏优化方案
前端·javascript
思扬09285 小时前
前端学习日记 - 前端函数防抖详解
前端·学习
gnip5 小时前
包体积,打包速度优化
前端·javascript
正义的大古5 小时前
Vue 3 + TypeScript:深入理解组件引用类型
前端·vue.js·typescript
A5rZ6 小时前
缓存投毒进阶 -- justctf 2025 Busy Traffic
前端·javascript·缓存
未来之窗软件服务7 小时前
浏览器CEFSharp133+X86+win7 之多页面展示(三)
前端·javascript·浏览器开发·东方仙盟
胡斌附体7 小时前
elementui cascader 远程加载请求使用 选择单项等
前端·javascript·elementui·cascader·可独立选中单节点
烛阴7 小时前
Vector Normaliztion -- 向量归一化
前端·webgl