mcpField
E
excalidraw

excalidraw

github.com/agents365-ai设计与 UI974.6k 次安装2 周前更新
代码仓库

关于 excalidraw

用于生成 Excalidraw 图表并导出为 PNG 或 SVG 的技能,涵盖规划、渲染和检查;可用 Kroki 导出 SVG,或用本地 CLI 导出 PNG。

主要功能

  1. 01生成 .excalidraw JSON
  2. 02通过 Kroki 导出 SVG
  3. 03本地导出 PNG 和 SVG
  4. 04检查并调整渲染结果
  5. 05使用社区矢量图形库

适用场景

  1. 01展示含多个交互组件的系统
  2. 02说明流程和决策树
  3. 03并列比较不同架构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/agents365-ai/365-skills --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

无需额外设置。通过 https://kroki.io 渲染 SVG。

选项 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:**无需补丁。

工作流

  1. 检查依赖项——导出 SVG 时使用 Kroki(curl);导出 PNG 时使用本地 CLI
  2. 规划——选择视觉隐喻(参见关系与布局对应表),然后确定图表类型和配色方案
  3. 生成——编写 .excalidraw JSON 文件(大型图表按章节编写)
  4. 导出——运行 Kroki 或 CLI 命令
  5. 验证渲染结果——查看导出的 PNG,修复缺陷后重新导出(参见验证渲染结果)
  6. 审阅迭代——向用户展示图像,根据请求对 .excalidraw 做最小修改,然后重新导出,直到用户批准(参见审阅迭代)
  7. 报告——告知用户输出文件路径

设计原则

默认样式
  • 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,而通过导出路径渲染 frames/embeds 的效果不一致。请仅使用以上六种类型;如需使用基于这些基本图形制作的现成图标,请参阅下文的 社区形状与图标库。

社区形状与图标库

需要真正的 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 渲染:

属性有效值
fillStyle"solid"、"hachure"、"cross-hatch"、"zigzag"
strokeStyle"solid"(或省略)、"dashed"、"dotted"
fontFamily1(Virgil,手绘)、2(Helvetica)、3(Cascadia,代码)
textAlign"left"、"center"、"right"
verticalAlign"top"、"middle"、"bottom"
startArrowhead / endArrowheadnull、"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 层分支放置在一个圆上,圆半径为 R ≈ 280,圆心为 (cx, cy):对于 n 个分支中的第 i 个,angle = 2π·i/n,x = cx + R·cos(angle),y = cy + R·sin(angle)。均匀间隔可避免随意摆放造成的线条交错缠绕。
泳道图
  • 使用大型透明矩形(Neutral 填充、"dashed" 描边、不透明度:30)作为泳道边界
  • 泳道标签作为独立文本放在泳道左上角(不绑定到矩形),字体大小为 28px
  • 元素在泳道内从左向右流动
  • 使用箭头跨泳道表示交接

分节构建

对于包含 10 个或更多元素的图表,切勿一次性生成整个 JSON。分节构建:

  1. 先规划所有章节 — 列出元素 ID、位置和跨章节绑定关系
  2. 编写第 1 节 — 创建文件并添加初始元素
  3. 追加第 2 节 — 读取文件,将新元素添加到 elements 数组中
  4. 重复上述步骤 — 继续操作,直到完成所有章节
  5. 最后检查 — 确认所有 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 看起来可能完美无缺,但图像中却可能有文字被裁切、方框重叠,或箭头穿过形状。导出后,查看效果并修复问题——这是收益最高的一步。

  1. 渲染为 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),则改用下面的结构检查。

  2. 检查图像:

    检查项修复方法
    文字被裁切 / 超出形状加宽形状(max(160, charCount * 9),CJK 字符需 ×2),或用 \n 手动换行
    方框或标签重叠根据间距参考重新调整位置(间隔 ≥40px)
    箭头笔直地穿过形状将端点移到形状边缘,而不是中心
    箭头不可见——只显示其标签缩小标签的 width,使其适合文字
    元素超出画布范围,或悬空且未连接重新定位 / 连接元素
    同构测试: 在脑海中删除所有文字——仅凭结构还能传达意思吗?如果不能,问题出在布局,而不是标签——请重新组织布局
  3. 修复 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);CJK 字符宽度加倍
boundElements: [] 导致问题空的 boundElements 使用 null,切勿使用 []

评论

支持 Markdown