· 运行时链路
职责划分
引擎在运行时是一组围绕事件总线协作的单例 Manager。核心原则:FrameManager 只发帧事件、不渲染;渲染由 CanvasRenderer 独立完成。
| 组件 | 职责 | 实例粒度 |
|---|---|---|
FrameManager | 把 requestAnimationFrame 回调统一转成 ICE_FRAME_EVENT 事件 | 全局单例(跨所有 ICE 实例共享) |
EventBus | 每 ICE 实例一条的事件总线,Manager 之间的协作通道 | 每 ICE 一条 |
DOMEventDispatcher | 把原生 DOM 事件(mouse/keyboard/touch)转成 ICEEvent 注入总线 | 每 ICE 一个 |
DOMEventInterceptor | 拦截文档级 DOM 事件,做统一预处理 | 全局(跨 ICE) |
AnimationManager | 订阅帧事件,对动画组件做补间(tween) | 每 ICE 一个 |
ICEControlPanelManager | 管理选中/变换工具(控制面板) | 每 ICE 一个 |
CanvasRenderer | 脏检查 + 脏矩形局部重绘(默认 dirty-rect,条件回退全量重绘),唯一真正操作 ctx 的调度方 | 每 ICE 一个 |
ICELinkSlotManager | 管理连接线插槽(LinkSlot)的复用与碰撞检测 | 每 ICE 一个 |
帧调度管道
关键点:
FrameManager是全局单例。同一个window/global里只有一个实例,它维护一个evtBuses数组,逐条触发ICE_FRAME_EVENT。因此一个页面上可以同时存在多幅图,共享同一个 rAF 循环。CanvasRenderer只在ice.dirty为真时渲染。脏标记是"惰性渲染"的开关:setState/结构变更会置dirty=true,下一帧才真正重绘,最小延迟约一帧(1/60 ≈ 16.7ms)。- 渲染分派:默认
dirty-rect只重绘脏区域(旧∪新世界盒),不满足局部条件(结构变更/快照未就绪/脏占比或面积过大/场景含文本·点集路径·半透明落墨等)时自动回退doRenderFull()全量重绘。组件 render 末尾会归位泄漏的 ctx 属性,保证两条路径逐像素一致。详见 04 与 AGENTS「脏矩形局部重绘铁律」。