在 Three.js 中,动画是创建互动和动态 3D 内容的关键组件。无论是为游戏、可视化工具,还是艺术项目添加动画效果,使用动画库都能极大地简化这个过程。本篇博客将梳理一些常用的动画库及其在 Three.js 中的应用,帮助开发者更好地理解和使用这些工具。
# 1. Tween.js
Tween.js 是一个简单但功能强大的动画库,专为在 JavaScript 中实现平滑动画而设计。它主要用于在指定时间内逐步改变对象的属性值。
基本使用方法:
// 创建一个初始状态的对象 | |
var position = { x: 0, y: 0 }; | |
// 创建一个 Tween 实例,目标状态为 x: 100, y: 100,持续时间为 2 秒 | |
var tween = new TWEEN.Tween(position) | |
.to({ x: 100, y: 100 }, 2000) | |
.easing(TWEEN.Easing.Quadratic.Out) // 使用缓动函数 | |
.onUpdate(function () { | |
// 在更新时改变对象的属性值 | |
console.log(position.x, position.y); | |
}) | |
.start(); | |
// 在动画循环中更新 TWEEN | |
function animate(time) { | |
requestAnimationFrame(animate); | |
TWEEN.update(time); | |
} | |
animate(); |
Three.js 中的应用: 在 Three.js 中,Tween.js 常用于动画移动、缩放、旋转 3D 对象。例如,将一个立方体从一个位置平滑移动到另一个位置:
var cube = new THREE.Mesh(geometry, material); | |
scene.add(cube); | |
var targetPosition = { x: 50, y: 50, z: 50 }; | |
var tween = new TWEEN.Tween(cube.position) | |
.to(targetPosition, 2000) | |
.easing(TWEEN.Easing.Elastic.Out) | |
.start(); |
Tween.js API
方法 | 描述 | 参数 |
---|---|---|
TWEEN.Tween(object) | 创建一个新的 Tween 实例 | object :要动画化的对象 |
.to(properties, duration) | 定义动画的目标属性和持续时间 | properties :目标属性值对象 duration :动画持续时间(毫秒) |
.easing(easingFunction) | 设置动画的缓动函数 | easingFunction :缓动函数 |
.onUpdate(callback) | 设置在每次动画更新时调用的回调函数 | callback :更新回调函数 |
.start([time]) | 开始动画 | time (可选):动画开始时间 |
.stop() | 停止动画 | 无 |
.delay(amount) | 设置动画开始前的延迟时间 | amount :延迟时间(毫秒) |
.repeat(times) | 设置动画重复的次数 | times :重复次数, Infinity 表示无限次 |
.yoyo(enable) | 设置是否在每次重复时反转动画方向 | enable :布尔值, true 表示启用 yoyo |
.chain(tween) | 设置动画链,当当前动画结束时,链中的下一个动画开始 | tween :下一个 Tween 实例 |
链式动画
可以通过链式调用创建连续的动画。
const tween1 = new TWEEN.Tween(coords) | |
.to({ x: 2, y: 2, z: 2 }, 2000) | |
.easing(TWEEN.Easing.Quadratic.Out); | |
const tween2 = new TWEEN.Tween(coords) | |
.to({ x: 0, y: 0, z: 0 }, 2000) | |
.easing(TWEEN.Easing.Quadratic.In); | |
tween1.chain(tween2); | |
tween1.start(); |
循环动画
可以创建循环动画,使对象不断重复某个动作。
const tween = new TWEEN.Tween(coords) | |
.to({ x: 2, y: 2, z: 2 }, 2000) | |
.easing(TWEEN.Easing.Quadratic.Out) | |
.repeat(Infinity) // 无限循环 | |
.yoyo(true) // 往返运动 | |
.start(); |
延迟动画
可以通过 delay()
方法为动画添加延迟。
const tween = new TWEEN.Tween(coords) | |
.to({ x: 2, y: 2, z: 2 }, 2000) | |
.easing(TWEEN.Easing.Quadratic.Out) | |
.delay(1000) // 延迟 1 秒 | |
.start(); |
# 2. GSAP (GreenSock Animation Platform)
GSAP 是一个功能强大且性能优化的动画库,常用于复杂动画和时间线控制。GSAP 提供了丰富的动画效果和控制功能,适用于各种复杂的动画需求。
基本使用方法:
// 使用 gsap.to 创建动画 | |
gsap.to(object.position, { | |
duration: 2, | |
x: 100, | |
y: 100, | |
ease: "power2.out", | |
onUpdate: () => console.log(object.position.x, object.position.y), | |
}); |
Three.js 中的应用: GSAP 在 Three.js 中非常适合处理复杂的时间线动画。例如,将一个立方体绕其中心旋转并同时改变其颜色:
var cube = new THREE.Mesh(geometry, material); | |
scene.add(cube); | |
gsap.to(cube.rotation, { | |
duration: 2, | |
x: Math.PI * 2, | |
ease: "power2.inOut" | |
}); | |
gsap.to(cube.material.color, { | |
duration: 2, | |
r: 1, | |
g: 0, | |
b: 0, | |
ease: "power2.inOut" | |
}); |
GSAP API
方法 | 描述 | 示例代码 |
---|---|---|
gsap.to() | 创建一个从当前属性值到目标属性值的动画。 | gsap.to(cube.position, { x: 2, y: 2, z: 2, duration: 2 }); |
gsap.from() | 创建一个从指定的属性值到当前属性值的动画。 | gsap.from(cube.position, { x: 2, y: 2, z: 2, duration: 2 }); |
gsap.fromTo() | 创建一个从指定的起始属性值到指定的目标属性值的动画。 | gsap.fromTo(cube.position, { x: 0, y: 0, z: 0 }, { x: 2, y: 2, z: 2, duration: 2 }); |
gsap.timeline() | 创建一个时间轴,用于顺序或并行运行多个动画。 | const tl = gsap.timeline(); tl.to(cube.position, { x: 2, duration: 2 }).to(cube.rotation, { y: Math.PI, duration: 2 }); |
repeat | 设置动画的重复次数。 | gsap.to(cube.position, { x: 2, repeat: -1, yoyo: true, duration: 2 }); |
delay | 为动画添加延迟。 | gsap.to(cube.position, { x: 2, delay: 1, duration: 2 }); |
ease | 设置缓动函数,以控制动画的加速度。 | gsap.to(cube.position, { x: 2, ease: 'power1.out', duration: 2 }); |
GSAP 时间轴
时间轴是 GSAP 强大的功能之一,可以让你轻松地创建顺序或并行的动画。
const tl = gsap.timeline({ repeat: -1, yoyo: true }); | |
tl.to(cube.position, { x: 2, duration: 2 }) | |
.to(cube.rotation, { y: Math.PI, duration: 2 }) | |
.to(cube.scale, { x: 2, y: 2, z: 2, duration: 2 }); |
# 3. Anime.js
Anime.js 是一个轻量级的动画库,支持各种动画效果和时间线控制。Anime.js 简单易用,且具有良好的性能,适用于不同类型的动画需求。
基本使用方法:
// 创建一个简单的动画 | |
anime({ | |
targets: object.position, | |
x: 100, | |
y: 100, | |
duration: 2000, | |
easing: 'easeInOutQuad', | |
update: () => console.log(object.position.x, object.position.y) | |
}); |
Three.js 中的应用: Anime.js 同样适用于 Three.js 中的动画。例如,为一个球体添加弹跳效果:
var sphere = new THREE.Mesh(sphereGeometry, material); | |
scene.add(sphere); | |
anime({ | |
targets: sphere.position, | |
y: [ | |
{ value: 50, duration: 500, easing: 'easeOutQuad' }, | |
{ value: 0, duration: 800, easing: 'easeInBounce' } | |
], | |
loop: true | |
}); |
anime.js API
方法 | 描述 | 示例代码 |
---|---|---|
targets | 定义动画作用的目标元素。 | targets: '.className' |
translateX | 沿 X 轴平移目标元素。 | translateX: 250 |
translateY | 沿 Y 轴平移目标元素。 | translateY: 250 |
scale | 缩放目标元素。 | scale: 2 |
rotate | 旋转目标元素。 | rotate: '1turn' |
duration | 动画持续时间(毫秒)。 | duration: 1000 |
delay | 动画开始前的延迟时间(毫秒)。 | delay: 500 |
easing | 设置缓动函数。 | easing: 'easeInOutQuad' |
loop | 设置动画循环次数。 | loop: true |
direction | 设置动画方向('normal','reverse','alternate')。 | direction: 'alternate' |
autoplay | 设置动画是否自动播放。 | autoplay: false |
begin | 动画开始时执行的回调函数。 | begin: () => { console.log('动画开始'); } |
complete | 动画完成时执行的回调函数。 | complete: () => { console.log('动画完成'); } |
时间线
时间线允许创建复杂的动画序列,多个动画可以顺序或并行执行。
const timeline = anime.timeline({ | |
duration: 1000, | |
easing: 'easeInOutQuad' | |
}); | |
timeline | |
.add({ | |
targets: '.className', | |
translateX: 250 | |
}) | |
.add({ | |
targets: '.className', | |
translateY: 250 | |
}) | |
.add({ | |
targets: '.className', | |
rotate: '1turn' | |
}); |
动画控制
可以通过播放、暂停和重启控制动画。
const animation = anime({ | |
targets: '.className', | |
translateX: 250, | |
duration: 1000, | |
autoplay: false | |
}); | |
document.querySelector('#playButton').addEventListener('click', animation.play); | |
document.querySelector('#pauseButton').addEventListener('click', animation.pause); | |
document.querySelector('#restartButton').addEventListener('click', animation.restart); |
# 4. 缓动函数
类别 | 缓动模式 | 描述 |
---|---|---|
Linear | TWEEN.Easing.Linear.None | 线性缓动,从头到尾以恒定速度移动。 |
Quadratic | TWEEN.Easing.Quadratic.In | 二次方缓动,动画以加速度开始。 |
TWEEN.Easing.Quadratic.Out | 二次方缓动,动画以减速度结束。 | |
TWEEN.Easing.Quadratic.InOut | 二次方缓动,动画以加速度开始和结束。 | |
Cubic | TWEEN.Easing.Cubic.In | 三次方缓动,动画以加速度开始。 |
TWEEN.Easing.Cubic.Out | 三次方缓动,动画以减速度结束。 | |
TWEEN.Easing.Cubic.InOut | 三次方缓动,动画以加速度开始和结束。 | |
Quartic | TWEEN.Easing.Quartic.In | 四次方缓动,动画以加速度开始。 |
TWEEN.Easing.Quartic.Out | 四次方缓动,动画以减速度结束。 | |
TWEEN.Easing.Quartic.InOut | 四次方缓动,动画以加速度开始和结束。 | |
Quintic | TWEEN.Easing.Quintic.In | 五次方缓动,动画以加速度开始。 |
TWEEN.Easing.Quintic.Out | 五次方缓动,动画以减速度结束。 | |
TWEEN.Easing.Quintic.InOut | 五次方缓动,动画以加速度开始和结束。 | |
Sinusoidal | TWEEN.Easing.Sinusoidal.In | 正弦缓动,动画以加速度开始。 |
TWEEN.Easing.Sinusoidal.Out | 正弦缓动,动画以减速度结束。 | |
TWEEN.Easing.Sinusoidal.InOut | 正弦缓动,动画以加速度开始和结束。 | |
Exponential | TWEEN.Easing.Exponential.In | 指数缓动,动画以加速度开始。 |
TWEEN.Easing.Exponential.Out | 指数缓动,动画以减速度结束。 | |
TWEEN.Easing.Exponential.InOut | 指数缓动,动画以加速度开始和结束。 | |
Circular | TWEEN.Easing.Circular.In | 圆形缓动,动画以加速度开始。 |
TWEEN.Easing.Circular.Out | 圆形缓动,动画以减速度结束。 | |
TWEEN.Easing.Circular.InOut | 圆形缓动,动画以加速度开始和结束。 | |
Elastic | TWEEN.Easing.Elastic.In | 弹性缓动,动画以加速度开始。 |
TWEEN.Easing.Elastic.Out | 弹性缓动,动画以弹性效果结束。 | |
TWEEN.Easing.Elastic.InOut | 弹性缓动,动画以加速度开始并以弹性效果结束。 | |
Back | TWEEN.Easing.Back.In | 回退缓动,动画开始前向后回退。 |
TWEEN.Easing.Back.Out | 回退缓动,动画结束后向后回退。 | |
TWEEN.Easing.Back.InOut | 回退缓动,动画开始前和结束后均向后回退。 | |
Bounce | TWEEN.Easing.Bounce.In | 弹跳缓动,动画以弹跳效果开始。 |
TWEEN.Easing.Bounce.Out | 弹跳缓动,动画以弹跳效果结束。 | |
TWEEN.Easing.Bounce.InOut | 弹跳缓动,动画以弹跳效果开始和结束。 |
选择合适的动画库可以极大地简化 Three.js 动画开发的复杂性。Tween.js、GSAP 和 Anime.js 各有优劣,开发者可以根据项目需求和个人偏好进行选择和组合使用。