Skip to content

build · 生成场景 ​

把几何、画法、主题合成场景:零件的 key 在这里规划,样式在这里解析成具体值。

导出 ​

buildScene、BuildOptions、ROOT_KEY。

签名 ​

ts
interface BuildOptions {
  registry: DrawRegistry;
  theme: ResolvedTheme;
  overlay?: StyleOverlay;
  measurer?: TextMeasurer;   // 传 layout 用的同一个,避免「量的盒子」与「画的文字」两套口径
}
function buildScene(
  input: DrawDocument | BoundDocument,
  layout: LayoutResult,
  options: BuildOptions,
): Result<Scene>;

新代码应传入 BoundDocument。为兼容 v1,也可以传原始文档,build 内部会先 bind。

这一步做四件事 ​

事口径
key 规划sink.key(suffix) 在固定前缀下分配稳定 key,重名才追加 #n
样式解析逐字段覆盖:默认画法 → typeStyles → 排版量 → document.styles[...] → overlay
派发画法registry.shapeSpec(type).render(ctx) / edgeSpec(type).render(ctx),形状自己摆零件
收集诊断SceneSink.warn 是 render 期诊断的唯一出口,和 build 自己的诊断汇到同一个数组

绘制顺序由结构推导 ​

容器背景(树先序)→ 边(含端点 marker)→ 叶子节点 → 边标签。

这条顺序让「线在节点下面、标签在节点上面」自动成立,不需要 z-index;host 只按 Scene 顺序输出。 marker 的大小固定 8,落点在 route 两端并自动转向(角度由首末折段推)。

样式合流 ​

两类元素各有底座,之后被更靠后的声明逐字段覆盖:

元素底座覆盖顺序
节点fill=surface / stroke=border / strokeWidth=1 / color=texttypeStyles → 排版量 → 文档样式 → overlay
边fill=none / stroke=edge / strokeWidth=1 / color=texttypeStyles → 排版量 → 文档样式 → overlay

{ token: "name" } 查 ResolvedTheme.tokens;查不到 → 退回到更早那一层的同名字段(最外层就是上面那两份底座)+ UNKNOWN_TOKEN(不抛)。 回落必须仍然给出一个可用值:把槽位丢掉会让形状掉到 SVG 的隐式默认(fill 黑),比不回落更难查。

只做 / 绝不做 ​

只做:把「绝对几何 + 画法 + 主题」翻译成场景树;入参只读。 绝不做:算坐标(几何来自 LayoutResult)、读宿主、吞掉未知类型。

  • 未知 shape / edge / marker 的回落已在 bind 处理,build 不重复发同类诊断。
  • shape / edge 使用 BoundDocument 中已经归一化的 props,不再重复执行 schema。
  • EdgeSpec.labels 缺省为 auto:build 读取 LayoutResult.labels[edge:id] 并统一绘制。
  • node / edge 在 LayoutResult 里没有几何 → LAYOUT_FAILED(error),整段 ok: false(这是唯一会让 build 失败的情况)。
  • 形状 / 边的 render 拿不到 document、LayoutResult、别的元素(L2 不变量,见 六段管线)。

相关 BDD ​

C11(未知 shape / port 回落 + 诊断)· C12(最小文档 → golden)· C13(两次 build 相等)· C14(复合形状子 key)· C23(不改入参)。

MIT License