主题
场景与增量
场景是“已经可以画出来的零件清单”。它不再关心文档语义,也不再计算布局,只保存绝对几何 和已经解析好的样式。
正在渲染图表…
一个场景由什么组成
每个零件都有唯一的 key、绝对坐标和 Style。零件可以带 ref,宿主做选择、悬停或拖拽时 直接读 { kind, id, part? },不必解析 key 字符串。
场景的顺序本身就是绘制顺序:
- 画布底;
- 容器背景;
- 边和箭头;
- 叶子节点;
- 边标签。
所以“线在节点下面、标签在节点上面”不需要 z-index,也不需要宿主自己排序。
key 为什么重要
增量更新不是比较整张 SVG,而是按 key 比较场景树。稳定 key 让宿主知道“这是同一个节点” 和“这是同一个标签”;key 一变,宿主只能删掉旧子树再重新创建。
节点注册时用 ctx.out.key(suffix) 生成 key,不要用随机数、时间或数组下标。复合形状的子 key 会自动带上父前缀,因此 icon 和 button/icon 不会互相覆盖。
diff 怎么判断变化
| 变化 | 结果 |
|---|---|
| 同一个 key,几何或样式变了 | update |
| 新增 key 或 kind 变了 | create |
| 节点被删除 | remove |
| 已有 key 的兄弟顺序变了 | move,不重建子树 |
插入或删除兄弟不会误触发 move;只有仍在场的 key 相对顺序改变时才发送 move。 hitTest(scene, point) 用场景几何从上到下返回 SceneRef[],适合选择框和点击命中。
diff 的目标是结果等价,不是生成尽可能少的 patch。这样规则简单,宿主也容易实现。
常见误解
- key 不稳定,就会把普通修改变成整棵子树重建。
- 场景里的坐标已经是绝对值,宿主不能再按父节点二次变换。
- diff 不负责布局;它只比较两份已经构建好的场景。
- 场景顺序有语义,手动重排可能改变遮挡关系。
Scene.bounds是内容边界,overflow单独记录阴影 / 发光溢出;相机边距由 host 解释。