关于 excalidraw
excalidraw 是一项用于生成 Excalidraw 图表 JSON 并导出为 PNG 或 SVG 的技能,面向需要绘制流程、系统或架构图的场景。它涵盖图表规划、样式规范、社区矢量图标库及渲染校验。
主要功能
- 01生成 Excalidraw JSON 文件
- 02通过 Kroki 导出 SVG
- 03通过本地 CLI 导出 PNG 和 SVG
- 04使用社区矢量图标库
- 05校验渲染并迭代修改
适用场景
- 01绘制系统架构与组件关系
- 02呈现多步骤流程或决策树
- 03并列比较不同架构方案
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ agents365-ai/ excalidraw-skill --skill excalidraw安装后在 Claude Code 中输入/excalidraw确认已加载。
附带文件references/schema-reference.mdscripts/excalidraw_lib.py
详细介绍
Excalidraw 图表
概述
生成 .excalidraw JSON 文件并导出为 PNG/SVG。
两种导出方式:
- Kroki API(
curl)——无需安装,仅输出 SVG - excalidraw-brute-export-cli——基于本地 Firefox,支持 PNG + SVG
**支持的格式:**PNG(仅本地 CLI)、SVG(两种方式均支持)。不支持 PDF。
使用场景
**明确触发词:**用户说“画图”“diagram”“visualize”“flowchart”“draw”“架构图”“流程图”
主动触发场景:
- 解释一个包含 3 个或更多交互组件的系统
- 描述多步骤流程或决策树
- 并排比较架构或方案
**跳过场景:**简单列表或表格就足以说明,或用户正在进行快速问答
不适用时——改用其他工具:
- 需要精美、精准的图表、严格的 UML,或带品牌标识的厂商图标 → drawio。
- 需要将图表作为代码纳入 git,或根据文本自动布局 → mermaid(通用场景)或 plantuml(UML)。
- 需要无限画布白板或以编程方式绘制自由笔触 → tldraw。
前置条件
选项 A:Kroki API(推荐——无需安装,仅支持 SVG)
# Just needs curl (pre-installed on macOS/Linux/Windows Git Bash)
curl --version
无需额外设置。SVG 通过 https://kroki.io 渲染。
选项 B:本地 CLI(导出 PNG 必需)
CLI 使用 Firefox(不是 Chromium)。检查并安装:
npm install -g excalidraw-brute-export-cli
npx playwright install firefox
macOS 补丁(一次性,必需):
CLI_MAIN=$(npm root -g)/excalidraw-brute-export-cli/src/main.js
sed -i '' 's/keyboard.press("Control+O")/keyboard.press("Meta+O")/' "$CLI_MAIN"
sed -i '' 's/keyboard.press("Control+Shift+E")/keyboard.press("Meta+Shift+E")/' "$CLI_MAIN"
**Windows/Linux:**无需补丁。
工作流
- 检查依赖——导出 SVG 使用 Kroki(curl);导出 PNG 使用本地 CLI
- 规划——选择视觉隐喻(参见关系到布局对照表),然后选择图表类型和配色方案
- 生成——编写
.excalidrawJSON 文件(大型图表按区块编写) - 导出——运行 Kroki 或 CLI 命令
- 验证渲染效果——查看导出的 PNG,修复缺陷后重新导出(参见验证渲染效果)
- 审阅循环——向用户展示图像,根据每项请求对
.excalidraw进行最小修改,然后重新导出,直至获得批准(参见审阅循环) - 报告——告知用户输出文件路径
设计原则
默认样式
roughness: 0——所有技术图表均采用简洁现代的风格(仅在用户要求手绘或随意风格时使用1)fontFamily: 2(Helvetica)——专业风格;仅在随意或草图风格时使用1(Virgil),代码片段使用3(Cascadia)fillStyle: "solid"——默认填充样式
容器:优先使用排版,而非方框
每个标签都加上方框会让图表看起来像线框图。最简洁的 Excalidraw 图表使用自由浮动的文本和线条来构建结构,仅将填充框用于真正的组件。
- 默认不使用容器——除非方框确有必要,否则使用独立的
text元素。 - **仅在以下情况下添加方框:**该元素是实际的系统组件、箭头需要连接到它、形状本身具有含义(决策菱形、起始或结束椭圆),或它用于划分区域。
- 目标是方框内的文本元素占比低于约 30%。
- 对于时间线、树和层级结构,使用线条/连接线 + 自由浮动标签,不要堆叠矩形。通过大小、粗细和颜色体现层级,无需使用方框。
字号层级
| 层级 | 大小 | 用途 |
|---|---|---|
| 标题 | 28px | 图表标题 |
| 页眉 | 24px | 分区/分组标题 |
| 标签 | 20px | 主要元素标签 |
| 描述 | 16px | 次要文本、描述 |
| 注释 | 14px | 注解、细则 |
配色
遵循 60-30-10 规则:60% 留白/中性色,30% 主强调色,10% 高亮色。
语义填充颜色(与深一档的 strokeColor 搭配使用):
| 类别 | 填充色 | 描边色 | 用途 |
|---|---|---|---|
| 主要/输入 | #dbeafe | #1e40af | 入口、API、面向用户的内容 |
| 成功/数据 | #dcfce7 | #166534 | 数据存储、成功状态 |
| 警告/决策 | #fef9c3 | #854d0e | 决策点、条件 |
| 错误/关键 | #fee2e2 | #991b1b | 错误、警报、关键路径 |
| 外部/存储 | #f3e8ff | #6b21a8 | 外部服务、数据库、AI/ML |
| 流程/默认 | #e0f2fe | #0369a1 | 标准流程步骤 |
| 触发器/开始 | #fed7aa | #c2410c | 起始节点、触发器、事件 |
| 中性/容器 | #f1f5f9 | #475569 | 分组、泳道、背景 |
文本颜色:
| 层级 | 颜色 |
|---|---|
| 标题 | #1e293b |
| 标签 | #334155 |
| 描述 | #64748b |
规则:不要自行添加新颜色。 从此配色方案中选择。
箭头语义
| 样式 | 含义 |
|---|---|
实线(strokeStyle: "solid") | 主要流程、主路径 |
虚线("dashed") | 响应、异步、回调 |
点线("dotted") | 可选、引用、弱依赖 |
Excalidraw JSON 结构
文件骨架
{
"type": "excalidraw",
"version": 2,
"source": "claude-code",
"elements": [],
"appState": { "viewBackgroundColor": "#ffffff" }
}
元素类型
| type | 用途 |
|---|---|
| rectangle | 方框、组件、模块 |
| ellipse | 起始/结束节点、数据库 |
| diamond | 决策点 |
| arrow | 有向连接 |
| line | 无向连接 |
| text | 独立标签 |
image、frame 和 embeddable 不在本技能涵盖范围内:image 需要单独的 files 映射以及 fileId,而通过导出路径渲染时,框架/嵌入内容的显示效果不一致。仅使用上述六种类型;若要使用由这些基本图形构建的现成图标,请参见下文的 社区形状与图标库。
社区形状与图标库
想用真正的 AWS/Azure/GCP/网络/UML/BPMN 图标,而不是普通方框?Excalidraw 社区库(200 多个 .excalidrawlib 文件)几乎完全由上述相同的矢量基本图形构成,因此其中的项目可通过 Kroki 和本地 CLI 渲染,无需 image 元素或 files 映射。使用 scripts/excalidraw_lib.py 中的辅助工具:
# 1. Find a library (matches name / description / item names)
python scripts/excalidraw_lib.py search aws
# 2. List its items (index, name, element count; flags any image-based item)
python scripts/excalidraw_lib.py items slobodan/aws-serverless.excalidrawlib
# 3. Build your base scene first, then drop an item in at (x, y). IDs are
# namespaced and coordinates translated, so it merges without collisions:
python scripts/excalidraw_lib.py merge scene.excalidraw \
slobodan/aws-serverless.excalidrawlib 0 455 257 --scale 0.9 --prefix lambda
规则:
- 仅限矢量图。
merge会拒绝任何包含image元素的项目(这些项目无法通过导出路径渲染);items会提前标记它们。 - 谨慎使用。 图标只是带标签的节点;请遵循设计系统的间距、标签和箭头语义。图标用于点缀图表,不能取代图表。
- 箭头不会绑定到库组——使用明确的边到边
points绘制连接线(无论如何,绑定不会影响静态导出)。 - 库采用 MIT 许可;欢迎酌情致谢,但并非必需。
- 随后仍需执行 验证渲染效果——图标的边界框尺寸各不相同,因此请检查对齐和间距。
元素尺寸
根据标签文本计算元素宽度,以避免文本被截断:
Latin text: width = max(160, charCount * 9)
CJK text: width = max(160, charCount * 18)
Mixed text: estimate each character individually, sum up
高度:单行标签使用 60,每增加一行再加 24。
独立的 text 不会自动换行。对于多行独立标签,请手动插入 \n 换行符;在 16px 字号下,每行尽量不超过约 30 个拉丁字符(约 15 个中日韩字符),并且每行增加 24 的高度。(通过 containerId 绑定在形状内的文本会自动按照容器宽度换行,因此应调整容器尺寸,而不是添加 \n。)
必需属性(所有元素)
{
"id": "auth_service",
"type": "rectangle",
"x": 100, "y": 100,
"width": 160, "height": 60,
"angle": 0,
"strokeColor": "#1e40af",
"backgroundColor": "#dbeafe",
"fillStyle": "solid",
"strokeWidth": 2,
"roughness": 0,
"opacity": 100,
"seed": 100001,
"boundElements": [
{ "id": "arrow_to_db", "type": "arrow" },
{ "id": "label_auth", "type": "text" }
]
}
使用描述性字符串 ID(例如 "api_gateway"、"arrow_gw_to_auth"),而不是随机字符串。
为每个元素指定唯一的 seed(整数)。按章节划分命名空间:100xxx、200xxx、300xxx。
JSON 字段规则
boundElements:为空时使用null,不要使用[]updated:始终使用1,不要使用时间戳- 不要包含:
frameId、index、versionNonce、rawText - 箭头的
points:始终从[0, 0]开始 seed:必须是正整数,且每个元素的值唯一
属性值
仅使用以下值——这些值均已验证可通过 Kroki 和本地 CLI 渲染:
| Property | Valid values |
|---|---|
fillStyle | "solid"、"hachure"、"cross-hatch"、"zigzag" |
strokeStyle | "solid"(或省略)、"dashed"、"dotted" |
fontFamily | 1(Virgil,手绘)、2(Helvetica)、3(Cascadia,代码) |
textAlign | "left"、"center"、"right" |
verticalAlign | "top"、"middle"、"bottom" |
startArrowhead / endArrowhead | null、"arrow"、"triangle"、"bar"、"dot"、"circle"、"diamond"、"crowfoot_many" |
箭头默认使用 endArrowhead: "arrow" 和 startArrowhead: null——标准单向箭头可省略两者。UML 继承使用 "triangle",组合使用 "diamond",ER 基数使用 "crowfoot_many"。
需要可直接复制粘贴的模板或完整的属性/箭头端点目录? 请阅读
references/schema-reference.md——其中包含完整的元素模板(组件+标签、绑定箭头、箭头标签、泳道区域、思维导图连接线)以及所有已验证的属性值。
形状内的文本(包含的文本)
当文本属于某个形状时,请双向绑定:
{
"id": "label_auth",
"type": "text",
"text": "Auth Service",
"fontSize": 20,
"fontFamily": 2,
"textAlign": "center",
"verticalAlign": "middle",
"strokeColor": "#1e293b",
"containerId": "auth_service"
}
重要:文本的 strokeColor 就是文本颜色。 务必明确将其设为文本调色板中的深色。不要省略它——文本省略 strokeColor 可能会导致文本不可见,与形状背景融为一体。
父形状必须在其 boundElements 中列出该文本:
"boundElements": [{ "id": "label_auth", "type": "text" }]
箭头绑定(双向)
箭头必须绑定到形状,形状也必须引用已绑定的箭头:
{
"id": "arrow_gw_to_auth",
"type": "arrow",
"points": [[0, 0], [200, 0]],
"startBinding": { "elementId": "api_gateway", "gap": 5, "focus": 0 },
"endBinding": { "elementId": "auth_service", "gap": 5, "focus": 0 }
}
api_gateway 和 auth_service 都必须在其 boundElements 中包含:
"boundElements": [{ "id": "arrow_gw_to_auth", "type": "arrow" }]
端点必须延伸至形状边框。 startBinding/endBinding(及其 gap)只影响在 excalidraw.com 上的交互式编辑——通过 Kroki 或本地 CLI 导出时,它们不会裁剪线条。导出器会按原样绘制 points。因此,请计算从边缘到边缘的端点:将箭头的 x/y 设为源形状朝向目标一侧的边框位置,并将最后一个点设为目标形状的边框位置。从中心到中心的点会使线条径直穿过两个形状。
箭头标签
要为箭头添加标签,请像绑定形状文本一样,将 text 元素绑定到箭头:将标签的 containerId 设为箭头的 ID,并将标签添加到箭头的 boundElements。这样,Excalidraw 会将标签居中放置在箭头上,并遮住文本后方的线条,使文字清晰易读(不会被线条穿过)。
{
"id": "arrow_valid_to_grant",
"type": "arrow",
"points": [[0, 0], [0, 120]],
"boundElements": [{ "id": "lbl_yes", "type": "text" }]
}
{
"id": "lbl_yes",
"type": "text",
"text": "Yes",
"fontSize": 14,
"width": 36,
"strokeColor": "#1e293b",
"containerId": "arrow_valid_to_grant"
}
重要:标签的 width 必须适合文本(charCount * 9),而不是箭头长度。 Excalidraw 会遮住标签整个边界框后方的线条——如果标签宽度与箭头一样,箭头就会被完全遮住,线条消失,只剩下悬浮的文字。因此,标签宽度应保持较小。
箭头路径
L 形(肘形)箭头——使用 3 个或更多点进行正交路径布线:
"points": [[0, 0], [100, 0], [100, 150]]
肘形箭头——自动进行直角路径布线:
{
"type": "arrow",
"points": [[0, 0], [0, -50], [200, -50], [200, 0]],
"elbowed": true
}
曲线箭头——使用路径点进行平滑路径布线:
{
"type": "arrow",
"points": [[0, 0], [50, -40], [200, 0]],
"roundness": { "type": 2 }
}
分组
相关元素共用 groupIds。嵌套分组中的 ID 按从最内层到最外层的顺序列出:
"groupIds": ["inner_group", "outer_group"]
图表模式
根据图表类型选择合适的视觉模式。
关系与布局映射
在确定图表类型之前,先选择与创意中的关系相匹配的视觉隐喻——相比类型标签,它对布局的影响更大:
| 创意中的关系 | 视觉隐喻 | 构建方式 |
|---|---|---|
| 一 → 多(广播、分发) | 扇出 | 一个节点,箭头向外辐射 |
| 多 → 一(聚合、合并) | 汇聚 | 多个输入,箭头汇入一个节点 |
| 父级 → 子级(层级结构) | 树 | 主干 + 分支线条,独立放置的文本 |
| 重复循环(循环、反馈) | 循环 | 节点排列成环,弯曲箭头返回起点 |
| 输入 → 转换 → 输出 | 流水线 | 从左到右排列的步骤流程 |
| A 与 B(比较) | 并排 | 两个平行列,共用一条基线 |
| 之前 / 之后、阶段划分 | 间隔 | 用留白或虚线分隔不同组 |
| 模糊 / 重叠状态 | 云 | 重叠的椭圆,不设硬边界 |
间距参考
| 场景 | 间距 |
|---|---|
| 带标签的箭头间距(形状之间) | 150–200px |
| 不带标签的箭头间距 | 100–120px |
| 列间距(带标签的箭头) | 400px(220px 方框 + 180px 间隔) |
| 列间距(不带标签的箭头) | 340px(220px 方框 + 120px 间隔) |
| 行间距 | 280–350px(150px 方框 + 130–200px 间隔) |
| 区域/容器内边距 | 子元素周围 50–60px |
| 区域/容器不透明度 | 25–40 |
| 任意元素之间的最小间距 | 40px |
流程图(LR 或 TB)
- 起点/终点用椭圆,决策用菱形,流程用矩形
- 水平间距 200px,垂直间距 150px
- 决策分支:“是”向前,“否”向下
- 3–10 个步骤(最多 15 个)
架构图 / 系统图
- 列间距遵循上表;连接带标签时使用带标签的箭头间距
- 将相关服务分组放入虚线
Neutral容器(不透明度:30,内边距:50px) - 网关/入口放在左侧或顶部,数据库放在右侧或底部
- 3–8 个实体(最多 12 个)
时序图
- 参与者之间间隔 200px(顶部的矩形)
- 垂直生命线使用虚线
- 消息使用水平箭头,垂直间距 60px
- 实线箭头 = 请求,虚线箭头 = 响应
思维导图
- 中心节点:最大(200x100),使用
Trigger颜色 - 第 1 层:150x70,使用
Primary颜色,围绕中心呈放射状排列 - 第 2 层:120x50,使用
Process颜色 - 第 3 层:90x40,使用
Neutral颜色 - 连接使用线条(而非箭头)
- 4–6 个分支(最多 8 个),每个分支包含 2–4 个子主题
- 将第 1 层分支沿圆周放置,圆心为
(cx, cy),半径为R ≈ 280:对于n个分支中的第i个,angle = 2π·i/n,x = cx + R·cos(angle),y = cy + R·sin(angle)。均匀间隔可避免临时摆放导致的线条交叉纠缠。
泳道图
- 使用大型透明矩形(
Neutral填充、"dashed"描边、不透明度:30)作为泳道边界 - 泳道标签作为独立文本放在泳道左上方(不绑定到矩形),字号 28px
- 元素在泳道内从左向右流动
- 箭头跨越泳道表示交接
分节构建
对于包含 10 个或更多元素的图表,不要一次性生成整个 JSON。分节构建:
- 先规划所有分节 — 列出元素 ID、位置和跨节绑定
- 编写第 1 节 — 创建包含初始元素的文件
- 追加第 2 节 — 读取文件,将新元素添加到
elements数组 - 重复上述步骤 — 继续操作,直至完成所有分节
- 最后检查 — 确认所有
boundElements和startBinding/endBinding引用一致
按分节为元素种子分配命名空间(100xxx、200xxx、300xxx),避免冲突。
导出
选项 A:Kroki API(仅 SVG — 无需安装)
# SVG via Kroki API
curl -s -X POST https://kroki.io/excalidraw/svg \
-H "Content-Type: text/plain" \
--data-binary "@diagram.excalidraw" \
-o diagram.svg
# Via local Kroki Docker (offline)
curl -s -X POST http://localhost:8000/excalidraw/svg \
-H "Content-Type: text/plain" \
--data-binary "@diagram.excalidraw" \
-o diagram.svg
选项 B:本地 CLI(PNG + SVG)
# PNG at 2x scale, with background baked in (recommended)
excalidraw-brute-export-cli -i diagram.excalidraw -o diagram.png -f png -s 2 -b true
# PNG at 1x scale
excalidraw-brute-export-cli -i diagram.excalidraw -o diagram.png -f png -s 1 -b true
# SVG
excalidraw-brute-export-cli -i diagram.excalidraw -o diagram.svg -f svg -s 1 -b true
必需标志: -f(格式:png 或 svg)和 -s(缩放:1、2 或 3)。
可选标志: -b true 会将 viewBackgroundColor 烘焙到图像中——默认导出为透明背景,因此只有在需要透明背景时才省略 -b(或传入 -b false)。-d true 导出深色模式;-e true 会嵌入场景,使 PNG/SVG 在 excalidraw.com 上重新打开时仍是可编辑的绘图。(长格式也可使用:--background、--dark-mode、--embed-scene、--format、--scale、--input、--output。)
验证渲染结果
无法仅凭 JSON 判断图表效果。 JSON 看起来可能完美无缺,但图像中却可能有被裁切的文字、重叠的方框,或穿过形状的箭头。导出后,查看结果并修正问题——这是最重要的一步。
-
渲染为 PNG(图像必须可查看——使用 PNG,而不是 SVG,即使用户最终需要的是 SVG):
excalidraw-brute-export-cli -i diagram.excalidraw -o /tmp/check.png -f png -s 2 -b true查看
/tmp/check.png(Claude 可直接读取 PNG)。视觉检查需要本地 CLI;如果只能使用 Kroki(SVG),则改为执行下方的结构检查。 -
检查图像:
检查项 修正方法 文字被裁切 / 溢出形状 加宽形状( max(160, charCount * 9),CJK 字符需 ×2),或使用\n预先换行方框或标签重叠 按照间距参考重新调整间距(间隔 ≥40px) 箭头笔直地穿过形状 将端点移到形状边缘,而不是中心 箭头不可见——只显示了标签 缩小标签的 width,使其适应文本元素超出画布,或悬空且没有连接 重新定位 / 连接元素 同构测试: 在脑海中删掉所有文字——仅凭结构还能传达意思吗? 如果不能,问题出在布局,而不是标签——请重新构造布局 -
修正 JSON 并重新导出。 重复上述步骤,直到没有问题为止——通常需要 1–3 轮。只有对于包含 2–3 个元素的简单图表,才可跳过此步骤。
审阅循环
验证渲染结果可以修复缺陷;审阅循环则会纳入用户的意愿。渲染结果检查无误后,将其展示给用户并收集反馈,然后针对每项请求进行最小化的 .excalidraw 编辑并重新导出:
| 用户请求 | 编辑操作 |
|---|---|
| 更改标签 | 编辑 text(或绑定的标签元素) |
| 更改颜色 | 更新元素上的 backgroundColor / strokeColor |
| 添加 / 删除元素 | 追加或删除元素(修正任何 boundElements / 绑定引用) |
| 移动 / 调整大小 | 更新 x / y / width / height |
| 重构 / 重新布线 | 重新应用对应模式的间距和布线规则,或重新生成 |
- 每轮都覆盖同一个
diagram.excalidraw/ 输出文件——不要创建v1、v2等文件。 - 每次编辑后都重新执行验证渲染结果(更改可能导致新的裁切 / 重叠)。
- **备用方案:**经过 5 轮后,建议用户在 excalidraw.com 中进行微调——输出会保留箭头绑定,因此打开后完全可编辑。
反模式
切勿在大型背景/区域矩形上放置 text。 Excalidraw 会将文本居中放在形状中间,与其中包含的元素重叠。应改用独立的 text 元素,将其放置在区域顶部。
避免跨区域箭头。 长对角箭头会造成视觉上的杂乱。请在区域内或沿区域边缘绘制箭头。如果无法避免跨区域连接,请沿外围绘制。
谨慎使用箭头标签。 将标签绑定到箭头(见 箭头标签),这样线条会被文本遮住,而不是穿过文本;但标签的 width 应仅与文本等宽,绝不能与箭头等长。标签长度控制在 ≤12 个字符,并确保连接的形状之间至少留有 ≥120px 的空白。如果根据上下文即可明确连接含义,则省略标签。
容器内含其他元素时,不要使用填充背景。 区域/容器矩形使用 opacity: 30(或 25-40 的范围),以确保其中的元素仍清晰可见。
始终为文本元素设置明确的 strokeColor。 文本的 strokeColor 就是渲染后的文本颜色。如果省略,文本可能会继承父形状的背景色,导致无法显示。请使用文本颜色调色板中的 #1e293b(标题)、#334155(标签)或 #64748b(说明)。
常见错误
| 错误 | 修复方法 |
|---|---|
| Kroki 返回 HTTP 400 | 发送 -H "Content-Type: text/plain"(不要使用 application/json,Kroki 会将其读取为 {"diagram_source": ...} 包装对象并拒绝);确保 JSON 有效,包含 "type": "excalidraw" 和 "elements" 数组 |
| Kroki 只输出 SVG | 使用本地 CLI(excalidraw-brute-export-cli)生成 PNG |
| 导出失败,提示 "Missing required flag" | 始终传入 -f png 和 -s 2 |
| 导出失败,提示 "Executable doesn't exist" | 运行 npx playwright install firefox |
| macOS:等待文件选择器超时 | 应用上文的 macOS Meta 补丁 |
箭头 points 未相对于原点设置 | points 始终从 [0,0] 开始 |
元素缺少 id | 为每个元素使用描述性字符串 ID |
| 元素重叠 | 使用间距参考表;间隙至少为 40px |
| 箭头在 excalidraw.com 中无法交互 | 在形状中添加 boundElements,引用所有绑定的箭头/文本 |
| 箭头/线条径直穿过形状 | 将端点设置在形状边缘,而不是中心——绑定不会裁剪静态导出图中的线条 |
| 箭头不可见,只有标签显示 | 绑定标签的 width 跨越整条箭头并遮住线条;将标签 width 设置为适合文本的宽度(charCount * 9) |
| 导出的 PNG/SVG 没有背景 | CLI 默认导出透明背景;传入 -b true,将 viewBackgroundColor 固化到图像中 |
| 文本未在形状中居中 | 在文本上设置 containerId,并将文本添加到形状的 boundElements |
| 所有文本大小相同 | 使用字号层级:28 → 24 → 20 → 16 → 14 |
| 图表看起来单调 | 使用调色板中的语义颜色,并遵循 60-30-10 规则 |
| 文本不可见/与背景同色 | 始终将文本元素的 strokeColor 设置为深色(#1e293b、#334155 或 #64748b) |
| 文本在区域/容器内重叠 | 不要将文本绑定到区域矩形;应将独立文本放在顶部 |
| 形状中的文本被截断 | 使用宽度公式:max(160, charCount * 9);中文字符的宽度加倍 |
boundElements: [] 导致问题 | 空的 boundElements 使用 null,绝不要使用 [] |