动画引擎原理 总览待审核
WAAPI · View Transitions · scroll-driven

与原生对照:浏览器自带了什么,为何仍手写引擎

浏览器原生提供三套动画能力:WAAPI(element.animate())做补间、 View Transitions(document.startViewTransition())做 DOM 状态切换的自动过渡、 scroll-driven animation(animation-timeline: scroll()/view())把动画声明式绑到滚动。 它们各有清晰的适用边界。本页用同一类效果分别对照演示,并解释这套手写引擎(@vega/anim)在 可 seek、可确定性测试、跨属性统一、不依赖浏览器实现这几点上补齐了什么。对不支持的 API 做 feature-detect, 不支持时降级为提示。

WAAPI · element.animate()

原生补间,返回 Animation 对象,可 pause / reverse / 写 currentTime。

@vega/anim · 手写引擎

同样的接口面,但游标 / 采样在 JS 内,可被手动驱动器确定性测试。

View Transitions · 列表重排

  • item · alpha
  • item · bravo
  • item · charlie
  • item · delta

把 DOM 改动包进 startViewTransition(),浏览器自动对前后快照做 morph。

scroll-driven · 滚动绑定(无 JS)

向下滚动这个容器,橙色进度条由 animation-timeline 直接驱动,JS 全程未参与。

WAAPI 状态 idle
能力WAAPIView Transitionsscroll-driven@vega/anim
seek / scrub不可由滚动隐式驱动
reverse不可由滚动方向决定
确定性测试依赖真实时钟依赖渲染快照依赖滚动环境可(手动驱动器)
跨属性统一(数字 / 颜色 / 弹簧)逐属性各异仅 crossfade / transformCSS 可动属性统一插值管线
自定义弹簧 / 衰减spring / decay
浏览器支持广泛较新(Chromium 先行)较新(Chromium 先行)仅需 JS 运行时
三套原生方案各有定位:其一 WAAPI 是离屏合成的原生补间,性能与 reverse / pause / 写 currentTime 都很好,但跨属性的语义并不统一,且没有弹簧 / 衰减这类物理模型;其二 View Transitions 解决的是 「DOM 从状态 A 切到状态 B 时的自动过渡」,适合路由切换、列表增删,但它不是一个可 seek / 可反向的播放器; 其三 scroll-driven 用声明式 CSS 把时间轴绑到滚动,零 JS,但时间轴只能来自滚动。手写引擎不与它们竞争「最省力」, 而是补齐可 seek、可确定性测试、跨属性统一插值、不依赖浏览器实现这组属性——把动画当作一条 时间 → 值 的纯函数管线,游标由可替换的驱动器推动, 因此既能接 rAF 实时跑,也能用手动驱动器在测试里逐帧推进。

实践中三者常并用:能用 scroll-driven 声明式表达的就别写 JS;页面 / 列表的状态切换交给 View Transitions; 而需要被精确 scrub、需要弹簧 / 惯性、需要在单元测试里断言每一帧的场景,用手写引擎。下面对照 WAAPI 与 View Transitions 的最小调用。

WAAPI vs View Transitions vs @vega/anim — 最小调用

  
scroll-driven animation — 声明式绑定滚动(无 JS)

  

手写引擎之所以能像 WAAPI 那样 pause / reverse / seek,根因见播放控制:为什么动画可以回退 (游标 + speed 的纯函数管线);把滚动当作驱动游标的输入、做成可 scrub 的滚动动画,见 交互驱动:手势与滚动