动画引擎原理 总览待审核
render target · canvas · sink 可换

渲染目标可换:同一引擎也能驱动 canvas

引擎产出的是,「把值写到哪」是另一回事。前面各页的值都落到 DOM (applyStyles 拼 transform); 但「时间 → 值」是纯函数,这个sink 可以随意替换:同一个主 Animation 当时钟, onUpdate(p) 里把每个粒子的位置采样出来,改成往 <canvas> 的 2D context 上画—— 渲染器换了,引擎一行没动。这也是动画即数据render 是纯函数那条主线的延伸。

一个主 Animation 驱动一片粒子,画到 canvas

几十个粒子从散布位置聚拢成一个环再散开 (repeatType: 'mirror' 往返)。一个 Animation 给出全局进度 p, 每个粒子的位置是它自己 起点 → 环上目标 的插值——和 DOM 版的关键帧采样完全一样,只是最后一步从写样式变成 ctx.arc。canvas 还能轻松做 DOM 难做的事:开「拖尾」不全清画布,留下运动残影。

sink = canvas 2D context;引擎与 DOM 版完全相同,只换了 onUpdate 里的最后一步。

引擎不关心 sink:值源 (关键帧 / 弹簧)、时序、播放控制都只产出数;把数写到 DOM transform、SVG 属性 (沿路径)、还是 canvas 像素,都只是 onUpdate 里的最后一步。canvas 适合大量逐像素带残影的视觉 (粒子 / 拖尾 / 程序化纹理),代价是失去 DOM 的命中测试与无障碍。声音等外部信号驱动的 canvas 可视化见声音驱动,无尽微动见噪声
@vega/anim — 同一引擎,sink 换成 canvas