动画引擎原理 总览待审核
AnimationWorklet · Houdini · off-main-thread

AnimationWorklet:把动画逻辑搬下主线程

本引擎的 tick 跑在主线程:主线程一忙 (大段同步 JS、布局抖动),rAF 就被推迟,动画掉帧。 合成层讲过 transform / opacity声明式动画能下到合成器线程、 不受主线程阻塞;但那只能表达固定关键帧。AnimationWorklet (CSS Houdini) 是平台给「让自定义 JS 动画逻辑 也跑在合成器线程」的答案:你写一个 animate(currentTime, effect) 函数注册成 animator,它在 worklet 线程逐帧运行。

注意:AnimationWorklet 至今是实验特性,只有 Chromium 系在特定条件下提供 (规范长期停滞),其余浏览器不支持。 下面先用一个所有浏览器都能跑的对照说明为什么需要它,再按你当前浏览器的支持情况尝试真正的 worklet。

为什么需要它:主线程一阻塞,谁还在动?

三条轨同时运动:rAF 由主线程逐帧驱动 (相当于本引擎的 driver);CSS compositor 是声明式 @keyframes transform,跑在合成器;worklet 若支持则由 worklet 线程驱动。点「阻塞主线程」跑一段 ~600ms 的同步死循环——只有主线程那条会卡住,合成器 / worklet 那条照常前进。

检测中…
主线程 rAF
CSS compositor
AnimationWorklet

点上面的按钮观察哪条卡住

掉帧的根因是「动画逻辑在哪条线程跑」:rAF 与本引擎的 tick 都在主线程,和你的业务 JS 抢同一条线程; transform/opacity 的声明式动画被浏览器下放到合成器线程 (见合成层), 所以主线程死循环时它照动。AnimationWorklet 的价值是:让带自定义 JS 逻辑的动画 (而不只是固定关键帧) 也能跑在 合成器侧。代价是它只能读受限的输入、不能碰 DOM,且支持度极差——所以现实中,绝大多数「不掉帧」的工程手段仍是 只动合成属性 + 单 rAF 与读写分离
AnimationWorklet — 自定义 animator 跑在 worklet 线程

  

为什么 rAF 必须按 delta-time 累加才帧率无关、阻塞时如何表现,见驱动器与帧; 哪些属性能下合成器、哪些会触发重排重绘,见合成层;一帧内如何批量读写避免强制同步布局, 见调度