跳到主要内容

补间动画

经常需要让实体或其他数值随时间从一种状态过渡到另一种状态,这称为补间动画(tweening)。playcanvas-tween 是 PlayCanvas 的补间动画库,支持缓动曲线、循环、往返和事件。

安装​

库提供两种构建,位于仓库的 dist 目录:

  • tween.umd.js:经典脚本。将其作为脚本资源添加到编辑器项目后,会为实体和应用添加 tween() 方法。如果应用在库加载后才创建,需要调用 app.addTweenManager(),为其启用补间动画。
  • tween.mjs:ES 模块,适用于 ESM 脚本和仅使用引擎的项目。可以调用 tweenEntity(),或调用一次 addTweenExtensions(),为实体和应用添加 tween() 方法:
import * as pc from 'playcanvas';
import { addTweenExtensions, SineOut } from './tween.mjs';

// adds tween() to entities and the application
addTweenExtensions(pc);

entity.tween(entity.getLocalPosition()).to({ x: 10, y: 0, z: 0 }, 1, SineOut).start();

实体补间动画​

entity.tween() 接收要执行动画的值,to() 接收目标值、以秒为单位的时长,以及缓动曲线。下面让实体的局部位置永久往返变化:

this.entity
.tween(this.entity.getLocalPosition())
.to(new Vec3(4, 0, 0), 1.0, SineOut)
.loop(true)
.yoyo(true)
.start();

旋转应使用 rotate() 而非 to()。它接受欧拉角或四元数,其中欧拉角会通过四元数进行插值:

this.entity
.tween(this.entity.getLocalEulerAngles())
.rotate(new Vec3(180, 0, 180), 1.0, Linear)
.loop(true)
.yoyo(true)
.start();

缩放的使用方式与位置相同:

this.entity
.tween(this.entity.getLocalScale())
.to(new Vec3(3, 3, 3), 1.0, SineOut)
.loop(true)
.yoyo(true)
.start();

其他数值的补间动画​

app.tween() 可以对颜色等任意对象执行补间动画。目标对象与原对象共有的属性会参与插值,并通过 onUpdate() 在变化时应用数值:

const color = new Color(0, 0, 0);
const material = this.entity.render.material;
this.app
.tween(color)
.to(new Color(1, 1, 1), 1.0, Linear)
.loop(true)
.yoyo(true)
.onUpdate(() => {
material.diffuse = color;
material.update();
})
.start();

上述演示来自 Using the Tween library 项目。

控制补间动画​

补间动画的方法可以链式调用:

方法说明
start()、stop()开始和停止补间动画。
pause()、resume()暂停和恢复补间动画。
delay(seconds)延迟开始。
repeat(count)播放 count 次。
loop(true)永久循环播放。
yoyo(true)每次正向播放后反向播放。需与 repeat 或 loop 结合,才能看到反向过程。
reverse()反转补间动画方向。

播放期间会调用以下回调:

回调说明
onUpdate(callback)每次更新时调用,传入时间步长。
onComplete(callback)补间动画结束时调用。
onLoop(callback)循环动画每完成一轮时调用,代替 onComplete。

缓动​

缓动曲线决定数值从起点到目标的变化方式。库提供 Linear,以及 Quadratic、Cubic、Quartic、Quintic、Sine、Exponential、Circular、Back、Bounce 和 Elastic 的 In、Out、InOut 变体,例如 SineOut 或 ElasticInOut。