在 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. 缓动函数

类别缓动模式描述
LinearTWEEN.Easing.Linear.None线性缓动,从头到尾以恒定速度移动。
QuadraticTWEEN.Easing.Quadratic.In二次方缓动,动画以加速度开始。
TWEEN.Easing.Quadratic.Out二次方缓动,动画以减速度结束。
TWEEN.Easing.Quadratic.InOut二次方缓动,动画以加速度开始和结束。
CubicTWEEN.Easing.Cubic.In三次方缓动,动画以加速度开始。
TWEEN.Easing.Cubic.Out三次方缓动,动画以减速度结束。
TWEEN.Easing.Cubic.InOut三次方缓动,动画以加速度开始和结束。
QuarticTWEEN.Easing.Quartic.In四次方缓动,动画以加速度开始。
TWEEN.Easing.Quartic.Out四次方缓动,动画以减速度结束。
TWEEN.Easing.Quartic.InOut四次方缓动,动画以加速度开始和结束。
QuinticTWEEN.Easing.Quintic.In五次方缓动,动画以加速度开始。
TWEEN.Easing.Quintic.Out五次方缓动,动画以减速度结束。
TWEEN.Easing.Quintic.InOut五次方缓动,动画以加速度开始和结束。
SinusoidalTWEEN.Easing.Sinusoidal.In正弦缓动,动画以加速度开始。
TWEEN.Easing.Sinusoidal.Out正弦缓动,动画以减速度结束。
TWEEN.Easing.Sinusoidal.InOut正弦缓动,动画以加速度开始和结束。
ExponentialTWEEN.Easing.Exponential.In指数缓动,动画以加速度开始。
TWEEN.Easing.Exponential.Out指数缓动,动画以减速度结束。
TWEEN.Easing.Exponential.InOut指数缓动,动画以加速度开始和结束。
CircularTWEEN.Easing.Circular.In圆形缓动,动画以加速度开始。
TWEEN.Easing.Circular.Out圆形缓动,动画以减速度结束。
TWEEN.Easing.Circular.InOut圆形缓动,动画以加速度开始和结束。
ElasticTWEEN.Easing.Elastic.In弹性缓动,动画以加速度开始。
TWEEN.Easing.Elastic.Out弹性缓动,动画以弹性效果结束。
TWEEN.Easing.Elastic.InOut弹性缓动,动画以加速度开始并以弹性效果结束。
BackTWEEN.Easing.Back.In回退缓动,动画开始前向后回退。
TWEEN.Easing.Back.Out回退缓动,动画结束后向后回退。
TWEEN.Easing.Back.InOut回退缓动,动画开始前和结束后均向后回退。
BounceTWEEN.Easing.Bounce.In弹跳缓动,动画以弹跳效果开始。
TWEEN.Easing.Bounce.Out弹跳缓动,动画以弹跳效果结束。
TWEEN.Easing.Bounce.InOut弹跳缓动,动画以弹跳效果开始和结束。

image.png

选择合适的动画库可以极大地简化 Three.js 动画开发的复杂性。Tween.js、GSAP 和 Anime.js 各有优劣,开发者可以根据项目需求和个人偏好进行选择和组合使用。