动画、关键帧、转场

这份文档描述的是当前时间线和动画系统的真实行为。

1. 动画调度模型

每个顶层 clip 的生命周期:

  1. 等待到 start
  2. 把节点加入场景
  3. 在该 clip 的有效时长内执行动画、关键帧和转场
  4. clip 生命周期结束

并行关系:

  • animationskeyframes 可以并行
  • audio clip 的 transition 也会并行执行
  • audio clip 会跑音量自动化,而不是视觉转场

2. Animation

interface Animation {
  type: AnimationType;
  duration: number;
  delay?: number;
  easing?: EasingFunction;
  loop?: boolean | number;
  from?: any;
  to?: any;
  direction?: "left" | "right" | "up" | "down";
  distance?: number;
}

当前支持的类型:

  • fadeIn
  • fadeOut
  • move
  • scale
  • rotate
  • slideIn
  • slideOut
  • zoomIn
  • zoomOut

3. 每个字段的行为

duration

  • 单位:秒
  • 必填
  • 如果 loop 开启,单次循环仍以这个值为基准

delay

  • 单位:秒
  • 可选
  • 同一个 delay 的动画会并行执行
  • 不同 delay 的动画按时间点依次执行

easing

  • 可选
  • 未填时默认 linear

loop

  • 类型:boolean | number
  • true:在当前 clip 剩余时长内尽可能重复执行
  • 数字:表示执行次数
  • 如果总循环时长超过 clip 时长,会自动截断

from

当前真正使用到 from 的类型:

  • scale
  • rotate
  • move

说明:

  • move.from 应该是 { x, y }
  • scale.from 可以是数字或二维值
  • rotate.from 应该是数字

to

当前真正使用到 to 的类型:

  • scale
  • rotate
  • move

说明:

  • move.to 应该是 { x, y }

direction

当前用于:

  • slideIn
  • slideOut

部分模板也会给某些预置动画塞 direction

distance

当前用于:

  • slideIn
  • slideOut

默认值:

  • 未填时通常用 200

4. 各动画类型详解

fadeIn

  • 起始透明度设为 0
  • 动画到原始透明度

fadeOut

  • 从当前透明度过渡到 0

zoomIn

  • 起始缩放设为 [0, 0]
  • 动画到原始缩放

zoomOut

  • 从当前缩放过渡到 [0, 0]

slideIn

  • 起始位置根据 direction + distance 偏移
  • 同时从透明度 0 过渡回来

slideOut

  • 结束时根据 direction + distance 偏移出去
  • 同时透明度过渡到 0

scale

  • 如果设置了 from,会先把缩放设到 from
  • 再过渡到 to
  • 没有 to 时回到原始缩放

rotate

  • 如果设置了 from,会先设到 from
  • 再过渡到 to
  • 没有 to 时默认转到 360

move

  • fromto 都应该写成对象
  • 例子:
{
  "type": "move",
  "duration": 1,
  "from": { "x": -200, "y": 0 },
  "to": { "x": 0, "y": 0 }
}

5. keyframes

interface Keyframe {
  property: string;
  frames: KeyframeFrame[];
}

interface KeyframeFrame {
  time: number;
  value: any;
  easing?: EasingFunction;
}

当前确认支持的属性:

  • x
  • y
  • position
  • opacity
  • scale
  • rotation
  • width
  • height
  • fill
  • stroke

行为说明:

  • frames 会先按 time 排序
  • 第一个关键帧会直接设值
  • 后续关键帧之间按插值执行
  • 最后一个关键帧之后会等待到 clip 结束

6. Transition

interface Transition {
  type: "fade" | "slide" | "zoom" | "wipe";
  duration: number;
  direction?: "left" | "right" | "up" | "down";
  easing?: EasingFunction;
}

当前支持:

  • fade
  • slide
  • zoom
  • wipe

真实行为:

  • 每个转场包含进场和出场两段
  • 两段都使用 transition.duration
  • 如果两段总时长超过 clip 时长,会自动截断到一半

7. 各转场类型详解

fade

  • 进场:透明度 0 -> 原始透明度
  • 出场:原始透明度 -> 0

slide

  • 进场:从画布外按方向滑入
  • 出场:按方向滑出到画布外
  • 同时带透明度变化

zoom

  • 进场:从较小缩放进入并淡入
  • 出场:放大并淡出

wipe

  • 通过缩放轴近似实现擦除效果
  • 左右方向收缩水平轴
  • 上下方向收缩垂直轴

8. Easing 列表

当前完整支持:

  • linear
  • easeInSine
  • easeOutSine
  • easeInOutSine
  • easeInQuad
  • easeOutQuad
  • easeInOutQuad
  • easeInCubic
  • easeOutCubic
  • easeInOutCubic
  • easeInQuart
  • easeOutQuart
  • easeInOutQuart
  • easeInBack
  • easeOutBack
  • easeInOutBack
  • easeInElastic
  • easeOutElastic
  • easeInOutElastic
  • easeInBounce
  • easeOutBounce
  • easeInOutBounce

9. 音频时间控制

audio clip 除了普通 start / duration 外,还支持:

  • source.start
  • source.end
  • fadeIn
  • fadeOut

这几项共同决定:

  • 何时开始播放
  • 播放素材的哪个片段
  • 播放过程中音量如何变化

10. 示例:标题进场 + 停留 + 出场

{
  "type": "text",
  "start": 0,
  "duration": 4,
  "text": "Hello",
  "transform": {
    "x": "50%",
    "y": "50%"
  },
  "style": {
    "fontSize": 72,
    "fill": "#ffffff"
  },
  "animations": [
    {
      "type": "slideIn",
      "direction": "up",
      "distance": 120,
      "duration": 0.6,
      "easing": "easeOutCubic"
    },
    {
      "type": "fadeOut",
      "delay": 3.2,
      "duration": 0.6,
      "easing": "easeInSine"
    }
  ],
  "transition": {
    "type": "fade",
    "duration": 0.25
  }
}