补间动画在霓虹 UI 中的应用:让界面"活"起来的 1200 毫秒

举报
yd_296221794 发表于 2026/09/10 09:26:05 2026/09/10
【摘要】 > 补间(Tween)是 Phaser 的"动画语言"——它让静态的 UI 元素有了"呼吸"。## 什么是补间动画在游戏开发里,"补间"(Tween)的意思是:**你描述"从哪到哪",引擎帮你算"中间怎么动"**。NEON RUNNER 2077 里用补间动画的地方至少有 5 处:| 场景 | 对象 | 动画类型 | 时长 ||---|---|---|---|| PreloadScene |...

> 补间(Tween)是 Phaser 的"动画语言"——它让静态的 UI 元素有了"呼吸"。


## 什么是补间动画


在游戏开发里,"补间"(Tween)的意思是:**你描述"从哪到哪",引擎帮你算"中间怎么动"**。


NEON RUNNER 2077 里用补间动画的地方至少有 5 处:


| 场景 | 对象 | 动画类型 | 时长 |

|---|---|---|---|

| PreloadScene | 进度条 | Counter(数值驱动) | 1800ms |

| PreloadScene | 加载消息 | 文字切换 | 300ms/条 |

| MenuScene | 副标题 | Alpha 呼吸 | 1200ms |

| MenuScene | 扫描线 | Y 轴扫描 | 2200ms |

| GameScene | 玩家 | Alpha 呼吸 | 800ms |

| GameScene | 占位文字 | Alpha 呼吸 | 1200ms |


## 呼吸动画:yoyo + repeat


`MenuScene` 里的副标题 "// 2 0 7 7 //" 有一个呼吸效果:


```ts

this.tweens.add({

  targets: this.subtitle,

  alpha: { from: 0.4, to: 0.9 },

  duration: 1200,

  yoyo: true,

  repeat: -1,

  ease: 'Sine.easeInOut',

});

```


`yoyo: true` 是关键——它让动画在到达终点后自动反向,而不是从头开始。如果没有 `yoyo`,动画会这样:


```

0.4 → 0.9(1200ms)→ 跳回 0.4 → 0.4 → 0.9(1200ms)→ 跳回 0.4 → ...

```


有 `yoyo`:


```

0.4 → 0.9(1200ms)→ 0.4(1200ms)→ 0.9(1200ms)→ 0.4(1200ms)→ ...

```


`repeat: -1` 表示无限循环。`ease: 'Sine.easeInOut'` 表示动画速度在两端变慢、中间变快——这是"呼吸"的典型曲线。


## 进度条动画:addCounter


`PreloadScene` 里的加载条用的是 `tweens.addCounter`,而不是 `tweens.add`:


```ts

this.tweens.addCounter({

  from: 0,

  to: 100,

  duration: 1800,

  ease: 'Sine.easeInOut',

  onUpdate: (_tween, _key, _target, current) => {

    const value = current / 100;

    this.progressBar.width = this.barWidth * value;

    this.percentText.setText(`${Math.floor(value * 100)}%`);

  },

});

```


`addCounter` 和 `add` 的区别:


- `add`:操作具体对象(`targets: this.subtitle`)

- `addCounter`:不操作对象,只给你一个 `current` 数值回调


为什么用 `addCounter`?因为进度条的宽度变化和文字更新是**两个独立的操作**——如果用 `add`,你需要把 `progressBar` 和 `percentText` 都放进 `targets` 数组,然后在 `onUpdate` 里分别更新。`addCounter` 更简洁。


## 扫描线动画:Y 轴扫描


`HoloPanel` 里的扫描线动画:


```ts

this.scanTween = scene.tweens.add({

  targets: this.scanLine,

  y: { from: -height / 2 + 2, to: height / 2 - 2 },

  duration: 2200,

  repeat: -1,

  yoyo: true,

  ease: 'Sine.easeInOut',

});

```


扫描线从面板顶部(`-height/2 + 2`)到底部(`height/2 - 2`),2200ms 一个来回。`yoyo: true` 让它"弹回来",而不是"跳回去"。


## 动画周期:为什么是 800ms、1200ms、2200ms


这些数字不是拍脑袋定的,而是基于**人类感知阈值**:


| 周期 | 感知效果 | 使用场景 |

|---|---|---|

| 400-600ms | 快速、醒目 | 场景切换(fade) |

| 800ms | 舒适、自然 | 玩家呼吸 |

| 1200ms | 平稳、不抢戏 | 副标题呼吸、占位文字 |

| 2200ms | 缓慢、有节奏感 | 扫描线 |


如果周期太短(比如 200ms),动画会"抖"——玩家会觉得"烦躁"。如果周期太长(比如 5000ms),动画会"消失"——玩家感觉不到"在动"。


## 缓动函数(Ease):Sine.easeInOut


NEON RUNNER 2077 里几乎所有动画都用 `Sine.easeInOut`。这个缓动函数的特点是:


- 开始时慢(ease in)

- 中间快

- 结束时慢(ease out)


这是"自然运动"的曲线——物体从静止开始加速,到达最高速度,然后减速停止。在 UI 动画里,`Sine.easeInOut` 比 `Linear`(匀速)更"柔和",比 `Quad.easeOut`(先快后慢)更"平稳"。


## 动画的层级:不要让所有东西同时动


NEON RUNNER 2077 里有一个重要的设计原则:**动画周期要错开**。


- 玩家呼吸:800ms

- 副标题呼吸:1200ms

- 扫描线:2200ms


如果所有动画的周期都是 800ms,它们会"共振"——玩家会觉得"整个画面在抖"。不同的周期让动画看起来更自然,像"不同物体在各自运动"。


## 下一章预告


补间动画讲完了,但 NEON RUNNER 2077 的视觉风格里还有一个关键元素——**扫描线与网格背景**。那些紫色细线和黑色横线是怎么画出来的?下一章我会拆解这个设计。


> 动画设计的核心原则:**动画是信息,不是装饰**。每个动画都应该告诉玩家"这个东西是活的"。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。