主题
host · 输出
把场景落到介质:一个出 SVG 字符串(headless,能在 Node / CI 里跑),一个写进 DOM(可交互 + 增量)。
导出
DrawHost、HostError、RenderToSvgOptions、renderToSvg、createDomHost。
签名
ts
interface DrawHost {
mount(scene: Scene): void;
apply(patch: ScenePatch[]): void;
destroy(): void;
}
function renderToSvg(
scene: Scene,
options?: { idPrefix?: string; padding?: number },
): string;
function createDomHost(
root: SVGSVGElement,
options?: { padding?: number },
): DrawHost;两个宿主,一份属性映射
| 宿主 | 入口 | 能力 |
|---|---|---|
string(renderToSvg) | @ggn/draw | 只支持全量,不接受 patch;纯字符串拼接,Bun / Node / CI 直接出 SVG |
DOM(createDomHost) | @ggn/draw/dom | mount / apply / destroy 全量,走 diffScene 的增量 |
两者共用同一份 Scene → SVG 属性 映射(svg-attrs.ts),所以对同一 Scene 输出的 key 与几何逐字一致,可以拿 string host 做 DOM host 的测试预言。
DOM 的 apply 会先完整校验一批 patch,再开始改介质。patch 非法或几何出现 NaN 时抛 HostError,介质保持上一帧;handle 会把它转成 HOST_FAILED 诊断。
相机与 id
viewBox/width/height由Scene.camera,或Scene.bounds + padding + overflow决定; 元素坐标一律不动(L3 不变量)。boundspatch 只更新相机,不改任何元素。- 没有显式
Scene.camera时,host 使用padding(默认 8)和Scene.overflow扩展内容紧包围盒; 有显式 camera 时直接使用 camera。 idPrefix只影响id(写成${idPrefix}:${encodeURIComponent(key)}),data-key始终是原始 key——同页多图防冲突不改变测试与选择的锚点。- 数值属性统一过有限性检查:
NaN/Infinity直接抛RangeError,不静默输出非法 SVG。
只做 / 绝不做
只做:把 Scene 翻成介质;按 key 做增量。 绝不做:算几何、认识 DrawDocument、认识领域语义。
正在渲染图表…
相关 BDD
C15(node 环境出合法 SVG + 前缀,全程不碰浏览器 API)· C16(string / DOM host 的 key 与几何一致)· C21 / C22(依赖只有 zod;主入口类型不含 DOM)。