在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 弹跳缓动,动画以弹跳效果开始和结束。

image.png

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