缓动动画的强大工具 Tween

在 Cocos Creator 中,Tween 是一个用于创建缓动动画的强大工具,它可以让你轻松地实现节点属性(如位置、缩放、旋转、透明度等)的平滑过渡。Tween 系统基于动作链,支持顺序、并行、重复、延迟等多种组合方式,并且内置了丰富的缓动函数(easing)。

本文将详细介绍 Tween 的用法,涵盖基本概念、常用 API、链式调用、缓动函数以及实际示例。

一、什么是 Tween?

Tween 是“补间动画”的简称,它的作用是在一定时间内,将一个对象的某个属性从起始值逐渐变化到目标值。在 Cocos Creator 中,Tween 可以作用于任何继承自 Node 的对象,也可以作用于普通 JavaScript 对象的数值属性。

Tween 的核心优势:

  • 简单易用:链式调用,代码简洁。
  • 功能强大:支持顺序、并行、重复、延迟、回调等。
  • 性能优化:内部使用对象池,减少 GC。
  • 与引擎集成:可自动处理生命周期(如组件销毁时停止动画)。

二、基本用法

1. 创建 Tween

通过 tween 函数创建一个 Tween 实例,它接收两个参数:

  • target:要动画的目标对象(通常是 Node 或任意对象)。
  • opts(可选):配置选项,如 progresseasing 等。
import { tween, Node, Vec3 } from 'cc';

const node = new Node();
const tw = tween(node); // 创建一个针对 node 的 Tween

2. 基本动作

Tween 提供了几个核心方法来定义动画行为:

方法

描述

.to(duration, props, opts?)

duration秒内将 props指定的属性从当前值变化到目标值。

.by(duration, props, opts?)

duration秒内将 props 指定的属性从当前值变化到当前值 + 增量。

.set(props)

立即设置目标对象的属性。

.delay(time)

延迟 time秒后执行后续动画。

.call(callback)

执行一个回调函数。

.repeat(repeatCount)

将前面的动作重复 repeatCount 次(总次数 = 1 + repeatCount)。

.repeatForever()

无限重复前面的动作。

.reverse()

将当前动作序列反向(通常用于创建来回动画)。

.union()

将当前动作序列合并为一个整体,以便进行重复或反向。

.parallel( ...tweens )

同时执行多个 Tween。

.then( otherTween )

在当前动作序列后追加另一个 Tween。

3. 启动与停止

创建好 Tween 后,必须调用 .start() 才会开始执行。

tw.start(); // 开始动画

其他控制方法:

  • .stop():立即停止动画。
  • .pause():暂停动画。
  • .resume():恢复暂停的动画。
  • .clone(target?):克隆当前 Tween,可指定新的目标对象。
  • .destroy():销毁 Tween 实例。

三、常用示例

1. 移动节点

// 1秒内从当前位置移动到 (100, 200)
tween(this.node)
  .to(1, { position: new Vec3(100, 200, 0) })
  .start();

2. 相对移动

// 1秒内向右移动 50 像素(相对于当前位置)
tween(this.node)
  .by(1, { position: new Vec3(50, 0, 0) })
  .start();

3. 同时改变多个属性

tween(this.node)
  .to(1, {
    position: new Vec3(200, 100, 0),
    scale: new Vec3(2, 2, 1),
    angle: 180
  })
  .start();

4. 顺序执行

// 先移动到 (100,0),再移动到 (100,100),最后移动到 (0,0)
tween(this.node)
  .to(1, { position: new Vec3(100, 0, 0) })
  .to(1, { position: new Vec3(100, 100, 0) })
  .to(1, { position: new Vec3(0, 0, 0) })
  .start();

5. 延迟与回调

tween(this.node)
  .delay(1)                       // 等待1秒
  .to(1, { opacity: 0 })           // 淡出
  .call(() => {                    // 完成后回调
    console.log('动画完成');
    this.node.destroy();
  })
  .start();

6. 重复动画

// 重复3次(总共执行4次)
tween(this.node)
  .to(1, { position: new Vec3(100, 0, 0) })
  .repeat(3)
  .start();

// 无限重复
tween(this.node)
  .by(1, { angle: 360 })
  .repeatForever()
  .start();

7. 来回运动(yoyo)

tween(this.node)
  .to(1, { position: new Vec3(200, 0, 0) })
  .reverse()               // 反向播放,回到起点
  .union()                  // 合并为整体
  .repeatForever()
  .start();

8. 并行动画

tween(this.node)
  .parallel(
    tween().to(1, { position: new Vec3(200, 0, 0) }),
    tween().to(1, { scale: new Vec3(2, 2, 1) }),
    tween().to(1, { angle: 360 })
  )
  .start();

注意:parallel 中的子 Tween 需要是 tween() 创建的,并且通常不需要指定目标(会自动继承父 Tween 的目标),但也可以显式指定目标。

四、缓动函数(Easing)

缓动函数控制动画的变化速率,使运动更自然。Cocos Creator 内置了多种缓动函数,可以通过 easing 参数指定。

tween(this.node)
  .to(2, { position: new Vec3(300, 0, 0) }, {
    easing: 'quadOut' // 先快后慢
  })
  .start();

常用缓动函数:

  • 'linear':匀速。
  • 'quadIn''quadOut''quadInOut':二次方缓动。
  • 'cubicIn''cubicOut''cubicInOut':三次方缓动。
  • 'quartIn''quartOut''quartInOut':四次方缓动。
  • 'quintIn''quintOut''quintInOut':五次方缓动。
  • 'sineIn''sineOut''sineInOut':正弦缓动。
  • 'expoIn''expoOut''expoInOut':指数缓动。
  • 'circIn''circOut''circInOut':圆形缓动。
  • 'elasticIn''elasticOut''elasticInOut':弹性缓动。
  • 'backIn''backOut''backInOut':回退缓动。
  • 'bounceIn''bounceOut''bounceInOut':弹跳缓动。

你也可以使用自定义的缓动函数:提供一个 (k: number) => number 函数。

五、对任意对象属性的动画

Tween 不仅限于节点,也可以用于普通对象:

const obj = { value: 0, color: 255 };

tween(obj)
  .to(2, { value: 100, color: 0 })
  .call(() => {
    console.log(obj.value, obj.color); // 100, 0
  })
  .start();

这在实现自定义数值渐变(如进度条、分数变化)时非常有用。

六、控制多个动画

你可以保存 Tween 实例以便后续控制:

const tw = tween(this.node)
  .to(3, { position: new Vec3(300, 0, 0) })
  .start();

// 稍后停止
tw.stop();

// 暂停
tw.pause();

// 恢复
tw.resume();

// 跳转到指定时间(秒)
tw.goTo(1.5);

七、结合组件生命周期

在 Cocos Creator 中,当挂载 Tween 的组件被销毁时,Tween 会自动停止,但你最好在 onDestroy 中手动清理,以防内存泄漏:

onDestroy() {
  tween(this.node).stopAllByTarget(this.node); // 停止所有关联该节点的 Tween
}

八、完整示例:按钮点击效果

import { _decorator, Component, Button, tween, Vec3 } from 'cc';

@ccclass('ButtonEffect')
export class ButtonEffect extends Component {
  onLoad() {
    this.node.on(Button.EventType.CLICK, this.onClick, this);
  }

  onClick() {
    // 先缩小再恢复
    tween(this.node)
      .to(0.1, { scale: new Vec3(0.9, 0.9, 1) })
      .to(0.1, { scale: new Vec3(1, 1, 1) })
      .start();
  }
}

九、注意事项

  • 坐标类型:在 3.x 版本中,位置、缩放等属性应使用 Vec3,不要使用普通对象。
  • 属性名:必须与目标对象上的实际属性名一致,例如节点有 positionscaleangleopacity 等。
  • 避免频繁创建:在 update 中创建 Tween 会导致大量对象,建议复用或使用对象池。
  • Widget 冲突:如果节点同时有 Widget 组件且启用了大小适配,修改 contentSize 可能会被覆盖。

十、总结

Cocos Creator 的 Tween 系统是一个功能完备、易用的动画解决方案,适合大多数 2D/3D 动画需求。通过组合 tobydelaycallrepeat 等动作,你可以实现几乎任何复杂的动画序列。结合缓动函数,动画效果更加自然。

建议在实际项目中多加练习,熟悉链式调用的组合方式,并注意性能优化(如复用 Tween、及时清理)。如果你需要更高级的控制(如动画曲线、动态参数),Tween 也能很好地满足。

全部评论

相关推荐

不愿透露姓名的神秘牛友
02-03 10:53
已编辑
华为云 Java开发 n*14 其他
牛客13617029...:感觉没啥理由选华为啊,二线薪资比一线还高
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务