Inline Visualizer(内联可视化器)
在对话里直接渲染富可视化内容——SVG 图、HTML 交互组件、图表。输出以 token 流方式逐字注入一个沙箱化 iframe,观感像对话的自然延伸,而不是一个附件。
工作原理
你生成原始 HTML 或 SVG 片段。客户端把它们渲染进一个沙箱化 iframe,并注入设计系统的 CSS 变量。不要写 <html>、<head>、<body> 标签——只写内容片段。
两种输出模式:
- SVG 模式:输出以
<svg>开头。客户端自动包进卡片。最适合静态图。 - HTML 模式:原始 HTML 片段。最适合交互内容(滑块、标签页、图表、控件)。你可以在 HTML 模式里内嵌
<svg>元素。
客户端根据输出是否以 <svg 开头来判断模式。
生成任何可视化之前
先读设计系统参考,再开始画第一个图:
- 永远先读:
references/design-system.md— CSS 变量、色阶、排版、核心规则 - 再读相关模块:
- 图(流程图、结构图、示意解释图):
references/diagrams.md - 交互讲解、对比、数据记录:
references/components.md - 图表(Chart.js、数据可视化):
references/charts.md
- 图(流程图、结构图、示意解释图):
每次对话读一次设计系统文件。每种图按需读对应模块文件。
流式约束
输出以 token 流注入 DOM。这决定了结构顺序:
- 先
<style>(控制在 15 行内——优先用内联样式) - 再放可见的 HTML/SVG 内容(用户能看到它逐步生成)
- 最后
<script>(流结束后才执行)
因为流式:
- 不要渐变、投影、模糊、发光——它们在 DOM diff 时会闪。用平涂填充。
- 不要
display:none或隐藏内容——会以不可见方式流出。 - 不要
<!-- 注释 -->或/* 注释 */——浪费 token、破坏流式。 - 优先用内联
style="..."而非<style>块,让元素在流式中途就正确显示。 - 不要起始隐藏的标签页或轮播——流式期间所有内容纵向堆叠展示。流式结束后的 JS 再加交互。
Iframe 沙箱规则
可视化渲染在沙箱化 iframe 里。这些是硬性约束:
- 不要 localStorage / sessionStorage — 所有状态必须在内存里
- 不要 position: fixed — iframe 按内容高度自动撑高;fixed 元素会让它塌掉
- 不要外部请求 — CSP 会拦截 widget 内的 API 调用
- 仅允许 CDN 白名单:
cdnjs.cloudflare.com、esm.sh、cdn.jsdelivr.net、unpkg.com - 不要 DOCTYPE、
<html>、<head>、<body>— 只写内容片段 - 背景透明——容器/卡片样式由宿主提供
- 通过
<script src="https://cdnjs.cloudflare.com/ajax/libs/...">加载库(UMD 全局变量)
sendPrompt 桥接
iframe 内可用全局函数 sendPrompt(text)。它把一条消息发到聊天,就像用户自己输入的一样。用它让可视化变得可对话——点击图里的节点可以触发后续讲解。
当用户下一步需要模型思考时才用 sendPrompt;筛选、排序、切换、计算放在本地 JS 里处理。
选对可视化类型
按"动词"而非"名词"路由。同一个主题,按被问的方式得到不同处理:
| 用户说 | 类型 | 该画什么 |
|---|---|---|
| "X 是怎么工作的" | 示意解释图 | 展示机制的立体隐喻 |
| "X 由哪些部分组成" | 结构图 | 带标签的盒子表示包含关系 |
| "带我走一遍步骤" | 流程图 | 顺序盒子加箭头 |
| "对比 X 和 Y" | 对比布局 | 左右并排的卡片带指标 |
| "把数据给我看" | 图表 | Chart.js 或内联数据可视化 |
| "解释 X"(空间概念) | 交互讲解 | 滑块、控件、实时状态 |
"X 是怎么工作的"默认画示意解释图——这是更进阶的选择。不要因为流程图更"安全"就退而求其次。
一次回复里放多个可视化
在一次回复里生成多个可视化,与文字交错:
- 文字块(引入/讲解)
- 可视化
- 文字块(过渡)
- 可视化(如需)
两个可视化之间绝不能没有文字直接堆叠。
输出包裹
把可视化输出包在语言标签为 visualizer 的代码围栏里,让客户端识别并路由到 iframe 渲染器:
```visualizer
<svg width="100%" viewBox="0 0 680 400">
...
</svg>
```
客户端剥离围栏,把内容注入 iframe,并在前面加上主题变量。
速查表
| 规则 | 值 |
|---|---|
| SVG viewBox 宽度 | 固定 680px |
| 字号 | 标签 14px,副标题 12px |
| 描边宽度 | 边框与连线 0.5px |
| 单图最多色数 | 2-3 个色阶 |
| 盒子副标题长度 | ≤5 个词 |
| 圆角(SVG) | rx="4" 默认,强调用 rx="8" |
| 圆角(HTML) | var(--border-radius-md) 或 -lg |
| 最小字号 | 11px |
| 字重 | 仅 400 常规、500 加粗 |
| 标题字号 | h1=22px,h2=18px,h3=16px |