主题
快速开始
画一张图要走五步:校验文档 → 解析主题 → 算几何 → 生成场景 → 输出。 每一步都能单独用,也能串起来一次做完(见五段管线)。
先看一眼它长什么样(这张图是当前代码实时渲染的):
零警告:整条管线没有产生任何诊断
bash
bun add @ggn/draw① 全自动:handle 接线
ts
import { parseDocument, createDrawHandle } from "@ggn/draw";
import { createDomHost } from "@ggn/draw/dom";
const parsed = parseDocument(json);
if (!parsed.ok) throw new Error(parsed.diagnostics.map((d) => `${d.code}: ${d.message}`).join("\n"));
const host = createDomHost(document.querySelector("svg")!);
const handle = createDrawHandle({ document: parsed.value, host });
// 第二帧起只产 patch;失败时保留上一帧
const diagnostics = handle.update(nextDocument);② 半自动:显式管线
每段的输出直接就是下一段的输入,中间结果全部可断言:
ts
import {
parseDocument, resolveTheme, createRegistry, builtinRegistry,
layoutDocument, buildScene, renderToSvg,
} from "@ggn/draw";
const doc = parseDocument(json);
if (!doc.ok) throw new Error(String(doc.diagnostics.length));
const theme = resolveTheme({ tokens: { accent: "#0f766e" } });
if (!theme.ok) throw new Error("theme");
const registry = createRegistry({ base: builtinRegistry }).registerShape("actor", actorShape);
const layout = layoutDocument(doc.value, { typography: theme.value.typography, metrics: registry.metrics() });
if (!layout.ok) throw new Error("layout");
const scene = buildScene(doc.value, layout.value, { registry, theme: theme.value });
if (!scene.ok) throw new Error("build");
const svg = renderToSvg(scene.value, { idPrefix: "uc" });③ 全手工:只换一段
任何一段都是注入点,其余不动:
| 想换什么 | 传什么 | 类型 |
|---|---|---|
| 布局算法 | layoutDocument(doc, { engine }) | LayoutEngine |
| 连线路由 | layoutDocument(doc, { router }) | Router |
| 文本度量 | layoutDocument / buildScene 的 measurer | TextMeasurer |
| 图元画法 | createRegistry({ base }).registerShape(...) | ShapeSpec |
| 介质 | 自己实现 DrawHost,或只消费 Scene | Scene |
两条入口
| 入口 | 用来做什么 | 约束 |
|---|---|---|
@ggn/draw | model / theme / registry / layout / scene / build / renderToSvg / createDrawHandle | 不出现 DOM API,直接 import 也不会碰浏览器 |
@ggn/draw/dom | createDomHost(root) | 唯一接触 DOM 的地方 |
失败与回落
ok: false只表示「产不出可用值」(结构非法、缺几何、入参不自洽),调用方必须处理。- 其余问题一律
ok: true+ 诊断:未知类型回落、未知 token 回落、props 非法用默认值。 - 每条诊断的
code是稳定契约,message只是给人看的。
ts
const scene = buildScene(doc, layout, { registry, theme });
if (scene.ok) {
const warnings = scene.diagnostics.filter((d) => d.severity === "warning");
}