mcpField
E
excalidraw

excalidraw

github.com/agents365-ai设计与 UI125 次安装
代码仓库

关于 excalidraw

excalidraw 是一项用于生成 Excalidraw 图表 JSON 并导出为 PNG 或 SVG 的技能,面向需要绘制流程、系统或架构图的场景。它涵盖图表规划、样式规范、社区矢量图标库及渲染校验。

主要功能

  1. 01生成 Excalidraw JSON 文件
  2. 02通过 Kroki 导出 SVG
  3. 03通过本地 CLI 导出 PNG 和 SVG
  4. 04使用社区矢量图标库
  5. 05校验渲染并迭代修改

适用场景

  1. 01绘制系统架构与组件关系
  2. 02呈现多步骤流程或决策树
  3. 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:**无需补丁。

工作流

  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,而通过导出路径渲染时,框架/嵌入内容的显示效果不一致。仅使用上述六种类型;若要使用由这些基本图形构建的现成图标,请参见下文的 社区形状与图标库。

社区形状与图标库

想用真正的 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 渲染:

PropertyValid values
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 层分支沿圆周放置,圆心为 (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。分节构建:

  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);中文字符的宽度加倍
boundElements: [] 导致问题空的 boundElements 使用 null,绝不要使用 []

评论

支持 Markdown