Excalidraw 技能与 Wireframe Pro 设计系统
📖 文档导航
- 快速上手: 5分钟指南
- 完整设计系统: Wireframe 规范
- 组件模板: 可复用组件
- 工具参考: MCP & REST API
🚀 快速开始
模式选择
- MCP 模式(推荐)- 工具列表中出现
excalidraw/*工具 - REST API 模式(备选)- 使用
http://127.0.0.1:3000HTTP 端点 - 服务器未运行? → 查看 服务器安装
常用操作速查
# 清空画布
clear_canvas
# 批量创建元素
batch_create_elements({"elements": [...]})
# 截图验证
get_canvas_screenshot
# 描述场景
describe_scene
# 设置视口
set_viewport({"scrollToContent": true})
典型工作流程
规划布局 → 创建元素 → 截图验证 → 质量检查 → 调整优化 → 完成
🎨 Wireframe Pro 设计规范(核心要点)
⚠️ 重要:绘制 UI 原型图时必须遵循以下核心规范。完整规范请查看 设计系统文档
三大核心原则
- 仅使用黑白灰 - 8 级色阶,禁止彩色
- 8px 网格对齐 - 所有坐标必须是 4 的倍数
- 组件规范统一 - 尺寸、圆角、字体标准化
色彩系统(必须使用)
#1A1A1A - 主文字、主按钮
#333333 - 副标题、次按钮边框
#666666 - 辅助文字
#999999 - 占位文字、未选中Tab
#CCCCCC - 边框、分割线
#E5E5E5 - 次级背景、海报占位
#F5F5F5 - 页面背景、输入框
#FFFFFF - 卡片背景、主按钮文字
间距系统(8px 基准)
04px - 极小间距(图标与文字)
08px - 小组件内间距
12px - 标准内间距(卡片padding)
16px - 区块内间距、移动端边距
24px - 区块间距
32px - 大区块间距、桌面端边距
48px - 超大间距(Hero区域)
64px - 页面级间距
圆角系统
0px - 直角(分割线、大背景)
4px - 小圆角(标签、徽章)
8px - 标准圆角(卡片、按钮、输入框)
12px - 大圆角(大卡片、弹窗)
16px - 超大圆角(轮播图)
9999px - 胶囊形(搜索框、Pill按钮)
字体规范
字体族:始终使用 "2" (Helvetica)
roughness:始终使用 0 (关闭手绘风格)
字号速查:
32px - Display(Hero大标题)
24px - H1(页面主标题)
20px - H2(卡片组标题)
18px - H3(区块标题)
16px - Body(正文、按钮)
14px - Caption(辅助信息)
12px - Small(标签、评分)
10px - Tiny(徽章)
组件尺寸标准
按钮:高度 44px,宽度 100-140px,圆角 8px
输入框:高度 44px,圆角 8px 或 9999px
导航栏:高度 56-64px
Tab栏:高度 44-56px
卡片内边距:12-16px
移动端边距:16px(左右)
桌面端边距:24-32px(左右)
Excalidraw 参数设置(必须)
{
"roughness": 0, // 关闭手绘风格
"strokeWidth": 1, // 细边框
"fontFamily": "2", // Helvetica
"opacity": 100 // 完全不透明
}
🔌 连接模式与工具对比
模式检测
两种模式可用。优先尝试 MCP — 功能更全面。
MCP 模式(推荐): 如果工具列表中出现 excalidraw/batch_create_elements 等 excalidraw/* 工具,直接使用。MCP 工具自动处理 label 和 arrow binding 格式。
REST API 模式(备选): 如果 MCP 工具不可用,使用 http://127.0.0.1:3000 的 HTTP 端点。查看 cheatsheet.md 获取 REST 负载说明。注意下方表格中的格式差异。
两者都无效? 告知用户:
服务器安装
Excalidraw 画布服务器未运行。安装步骤:
git clone https://github.com/yctimlin/mcp_excalidraw && cd mcp_excalidrawnpm ci && npm run buildPORT=3000 npm run canvas- 浏览器打开
http://127.0.0.1:3000- (推荐)安装 MCP 服务器:
claude mcp add excalidraw -s user -e EXPRESS_SERVER_URL=http://127.0.0.1:3000 -- node /path/to/mcp_excalidraw/dist/index.js
MCP vs REST API 快速对照
| 操作 | MCP 工具 | REST API 等效 |
|---|---|---|
| 创建元素 | batch_create_elements |
POST /api/elements/batch |
| 获取所有元素 | query_elements |
GET /api/elements |
| 获取单个元素 | get_element |
GET /api/elements/:id |
| 更新元素 | update_element |
PUT /api/elements/:id |
| 删除元素 | delete_element |
DELETE /api/elements/:id |
| 清空画布 | clear_canvas |
DELETE /api/elements/clear |
| 描述场景 | describe_scene |
GET /api/elements(手动解析) |
| 导出场景 | export_scene |
GET /api/elements(保存到文件) |
| 导入场景 | import_scene |
POST /api/elements/sync |
| 快照 | snapshot_scene |
POST /api/snapshots |
| 恢复快照 | restore_snapshot |
GET /api/snapshots/:name 然后 POST /api/elements/sync |
| 截图 | get_canvas_screenshot |
POST /api/export/image(需浏览器) |
| 视口 | set_viewport |
POST /api/viewport(需浏览器) |
| 导出图片 | export_to_image |
POST /api/export/image(需浏览器) |
| 导出链接 | export_to_excalidraw_url |
仅 MCP 支持 |
⚠️ 模式间格式差异(关键)
- 标签: MCP 接受形状上的
"text": "My Label"(自动转换)。REST 需要"label": {"text": "My Label"}。 - 箭头绑定: MCP 使用
startElementId/endElementId。REST 需要"start": {"id": "..."}/"end": {"id": "..."}。 - fontFamily: 必须是字符串(如
"1")或完全省略。绝不能传数字。 - REST 更新标签: 在 PUT 请求中重新包含
"label"确保更新后正确渲染。
完整工具列表和端点请参考 cheatsheet.md
📐 坐标系与布局原则
坐标系
画布使用 2D 坐标网格:(0, 0) 是原点,x 向右增加,y 向下增加。在编写任何 JSON 之前先规划布局。
间距通用指南
- 层级间垂直间距:80–120px(足够空间放置箭头标签)
- 同级间水平间距:至少 40–60px
- 形状宽度:
max(160, 标签字符数 * 9)防止文字截断 - 形状高度:单行 60px,双行 80px
- 背景/区域 padding:包含元素四周各 50px
布局反模式(复杂图表的关键错误)
这些是最常见的错误,会产生难以阅读的图表。必须避免:
❌ 1. 不要在大型背景区域矩形上使用 label.text(或 text)
当你在背景矩形上放置标签时,Excalidraw 会创建一个绑定的文本元素,位于该形状的正中央——这正是你要放置服务框的位置。文本会与区域内的所有内容重叠,且无法重新定位。
错误示例:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "text": "VPC (10.0.0.0/16)"}
正确方式 — 使用锚定在区域顶部的独立文本元素:
{"id": "vpc-zone", "type": "rectangle", "x": 50, "y": 50, "width": 800, "height": 400, "backgroundColor": "#e3f2fd"},
{"id": "vpc-label", "type": "text", "x": 70, "y": 60, "width": 300, "height": 30, "text": "VPC (10.0.0.0/16)", "fontSize": 18, "fontWeight": "bold"}
独立文本元素位于区域的左上角,不会干扰内部放置的元素。
❌ 2. 避免跨区域的箭头
从一个布局区域的元素到远处区域的箭头会绘制长长的对角线,穿过中间的所有内容。在多区域基础设施图中,这会产生难以阅读的混乱线条。
设计规则: 将箭头保持在同一区域或层级内。要显示跨区域关系,使用注释文本,或分离区域使它们边缘相邻(它们之间没有元素),并沿边缘路由箭头。
如果必须跨区域连接,使用肘形箭头沿着周边路由——绝不穿过另一个区域的中间。
❌ 3. 谨慎使用箭头标签
箭头标签放置在箭头的中点。在短箭头上,它们会重叠两端的形状。在拥挤的图中,它们会与附近元素碰撞。
- 仅当关系名称真正重要时才添加箭头标签(如协议、端口号、数据方向)
- 如果为每个箭头添加标签,重新考虑——通常会增加视觉噪音,而非清晰度
- 箭头标签保持在 ≤ 12 个字符。在密集图中最好完全省略
✅ 质量检查清单
Excalidraw 图表是视觉沟通工具。如果文字被截断、元素重叠或箭头穿过无关形状,图表会变得混乱且不专业——这违背了绘制的目的。每次批量创建元素后,在添加更多内容之前进行验证。
检查流程
每次 batch_create_elements / POST /api/elements/batch 后,截图并检查:
Wireframe Pro 规范检查(UI 原型图必须)
- 网格对齐 — 所有 x, y 坐标是 4 的倍数(优先 8 的倍数)
- 色彩规范 — 仅使用黑白灰 8 级色阶,无彩色
- 间距一致 — 同类型组件间距相同(12/16/24px)
- 尺寸统一 — 同类型卡片宽度、高度完全一致
- 圆角统一 — 同类型组件圆角一致(8px/9999px)
- 字体规范 — fontFamily="2", roughness=0, 字号符合规范
- 留白充足 — 移动端边距 16px,不拥挤
- 视觉层次 — 标题 > 正文 > 辅助文字,清晰可辨
通用质量检查
- 文字截断 — 所有标签文字是否完全可见?截断的文字意味着形状太小。增加
width和/或height。 - 重叠 — 是否有形状共享同一空间?背景区域必须通过 padding 完全包含子元素。
- 箭头穿越 — 箭头是否切割无关元素?如果是,使用曲线或肘形箭头绕过(见下方箭头路由)。
- 箭头标签重叠 — 箭头标签位于中点。如果它们重叠形状,缩短标签或调整箭头的路径。
- 间距 — 元素之间至少 40px 间隙。拥挤的布局难以阅读。
- 可读性 — 正文文字字号 ≥ 16,标题 ≥ 20。
- 区域标签放置 — 如果你在背景区域矩形上使用了
text/label.text,区域标签会位于区域中央,与内部所有内容重叠。修复:删除绑定的文本元素,在区域顶部添加独立的文本元素(见上方布局反模式)。
处理原则
如果发现问题:停止,修复,重新截图,然后继续。 说"我发现 [问题],正在修复",而不是忽略问题。只有在所有检查通过后才能继续。
🎯 工作流程:绘制新图表
Mermaid vs 直接创建 — 如何选择?
使用 create_from_mermaid 当:用户已有 Mermaid 图表,或结构能 cleanly 映射到流程图/序列图/ER 图的标准 Mermaid 语法。快速且自动处理转换,但对精确布局的控制较少。
直接使用 batch_create_elements 当:需要精确布局控制、图表类型不能很好地映射到 Mermaid(如自定义架构、带注释的云图),或希望元素定位在特定坐标网格中。
MCP 模式工作流
- 获取设计指南 — 调用
read_diagram_guide获取设计最佳实践(颜色、字体、反模式) - 规划坐标网格 — 在纸上/注释中映射层级和 x 位置,在编写 JSON 之前
- 清空画布(可选)— 调用
clear_canvas从头开始 - 批量创建元素 — 一次性创建形状和箭头。自定义
id字段(如"id": "auth-svc")使后续更新更容易 - 设置形状宽度 — 使用
max(160, 标签长度 * 9)。使用text字段作为标签 - 绑定箭头 — 使用
startElementId/endElementId— 它们自动路由到元素边缘 - 设置视口 — 调用
set_viewport并设置scrollToContent: true自动适配 - 截图验证 — 调用
get_canvas_screenshot→ 运行质量检查清单 → 在下次迭代之前修复问题
MCP 元素 + 箭头示例:
{"elements": [
{"id": "lb", "type": "rectangle", "x": 300, "y": 50, "width": 180, "height": 60, "text": "Load Balancer"},
{"id": "svc-a", "type": "rectangle", "x": 100, "y": 200, "width": 160, "height": 60, "text": "Web Server 1"},
{"id": "svc-b", "type": "rectangle", "x": 450, "y": 200, "width": 160, "height": 60, "text": "Web Server 2"},
{"id": "db", "type": "rectangle", "x": 275, "y": 350, "width": 210, "height": 60, "text": "PostgreSQL"},
{"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-a"},
{"type": "arrow", "x": 0, "y": 0, "startElementId": "lb", "endElementId": "svc-b"},
{"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-a", "endElementId": "db"},
{"type": "arrow", "x": 0, "y": 0, "startElementId": "svc-b", "endElementId": "db"}
]}
REST API 模式工作流
- 规划坐标网格 — 首先规划
- 清空画布(可选)—
curl -X DELETE http://127.0.0.1:3000/api/elements/clear - 创建元素 — 使用
POST /api/elements/batch。使用"label": {"text": "..."}作为标签 - 绑定箭头 — 使用
"start": {"id": "..."}/"end": {"id": "..."} - 验证 — 使用
POST /api/export/image→ 保存 PNG → 运行质量检查清单
REST API 元素 + 箭头示例:
curl -X POST http://127.0.0.1:3000/api/elements/batch \
-H "Content-Type: application/json" \
-d '{
"elements": [
{"id": "svc-a", "type": "rectangle", "x": 100, "y": 100, "width": 160, "height": 60, "label": {"text": "Service A"}},
{"id": "svc-b", "type": "rectangle", "x": 400, "y": 100, "width": 160, "height": 60, "label": {"text": "Service B"}},
{"type": "arrow", "x": 0, "y": 0, "start": {"id": "svc-a"}, "end": {"id": "svc-b"}, "label": {"text": "calls"}}
]
}'
🔀 箭头路由 — 避免重叠
在复杂图中,直线箭头可能穿过元素。必要时使用曲线或肘形箭头:
曲线箭头(平滑弧线绕过障碍物)
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [50, -40], [200, 0]],
"roundness": {"type": 2}
}
中间航点 [50, -40] 将箭头向上抬起。roundness: {type: 2} 使其平滑。
肘形箭头(直角/L 形路由)
{
"type": "arrow", "x": 100, "y": 100,
"points": [[0, 0], [0, -50], [200, -50], [200, 0]],
"elbowed": true
}
何时使用哪种
- 扇出(一个源 → 多个目标):带有航点的曲线箭头分散以避免重叠
- 跨通道(连接到侧面板):肘形箭头先上,再横穿,再下
- 长水平连接:带有轻微垂直偏移的曲线箭头
规则: 如果箭头会穿过无关形状,添加航点绕过它。
点格式:[[x, y], ...] 元组和 [{"x": ..., "y": ...}] 对象都被接受;两者都被自动标准化。
🔄 工作流程:迭代优化
结合使用 describe_scene 和 get_canvas_screenshot 是这个技能的强大之处。
describe_scene→ 返回结构化文本:元素 ID、类型、位置、标签、连接。当你在进行编程更新之前需要知道画布上有什么时使用(查找 ID、理解边界框)。get_canvas_screenshot→ 返回实际渲染画布的 PNG 图像。用于视觉质量验证——它向你准确显示用户看到的内容,包括截断、重叠和箭头路由。
MCP 反馈循环
batch_create_elements
→ get_canvas_screenshot → "auth-svc 上文字被截断"
→ update_element(增加宽度) → get_canvas_screenshot → "auth-svc 和 rate-limiter 重叠"
→ update_element(重新定位) → get_canvas_screenshot → "所有检查通过"
→ 继续
REST 反馈循环
POST /api/elements/batch
→ POST /api/export/image → 保存 PNG → 评估
→ PUT /api/elements/:id(修复问题) → 重新截图 → 评估
→ 继续
🔧 工作流程:优化现有图表
- 理解当前状态 — 调用
describe_scene了解当前状态 — 注意元素 ID 和位置 - 识别元素 — 通过
id或标签文本识别元素(不是通过 x/y 坐标——它们会变化) - 更新或删除 —
update_element调整大小/颜色/移动;delete_element删除 - 确认更改 —
get_canvas_screenshot确认更改看起来正确 - 更新失败? — 使用
get_element检查 ID 是否存在;使用unlock_elements检查是否未锁定
🔄 工作流程:Mermaid 转换
将现有 Mermaid 图表转换为 Excalidraw:
MCP 模式:
create_from_mermaid(mermaidDiagram: "graph TD\n A --> B\n B --> C")
转换后,调用 set_viewport 设置 scrollToContent: true 并调用 get_canvas_screenshot 验证布局。如果自动布局不佳(节点拥挤、边交叉),使用 describe_scene 识别问题元素并使用 update_element 重新定位。
REST 模式:
curl -X POST http://127.0.0.1:3000/api/elements/from-mermaid \
-H "Content-Type: application/json" \
-d '{"mermaid": "graph TD\n A --> B\n B --> C"}'
💾 工作流程:文件 I/O
- 导出为 .excalidraw:
export_scene带可选filePath - 从 .excalidraw 导入:
import_scene带mode: "replace"或"merge" - 导出为图像:
export_to_image带format: "png"或"svg"(需要浏览器打开) - 分享链接:
export_to_excalidraw_url— 加密场景,返回可分享的 excalidraw.com URL - CLI 导出:
node scripts/export-elements.cjs --out diagram.elements.json - CLI 导入:
node scripts/import-elements.cjs --in diagram.elements.json --mode batch|sync
快照管理
- 在风险更改之前使用名称调用
snapshot_scene - 进行更改,使用
describe_scene/get_canvas_screenshot评估 - 如需要,使用
restore_snapshot回滚
元素复制
duplicate_elements 带 elementIds 和可选 offsetX/offsetY(默认:20, 20)。适用于重复模式或复制布局。
🛠️ 错误恢复与故障排除
常见问题与解决方案
元素不显示?
- 检查:调用
describe_scene— 它们可能在屏幕外创建 - 解决:使用
set_viewport设置scrollToContent: true
箭头未连接?
- 检查:使用
get_element验证元素 ID - 确保:
startElementId/endElementId(MCP)或start.id/end.id(REST)匹配现有元素 ID
画布状态不佳?
- 首先:调用
snapshot_scene保存当前状态 - 然后:
clear_canvas并重新构建 - 或者:
restore_snapshot回退
元素无法更新?
- 可能原因:元素已锁定
- 解决:先调用
unlock_elements
导入后布局看起来不对?
- 检查:使用
describe_scene检查实际位置 - 修复:批量更新位置
重复的文本元素 / 元素数量翻倍?
- 原因:前端有自动同步计时器,定期发送完整的 Excalidraw 场景回服务器(覆盖)。Excalidraw 内部为每个具有
label.text的形状生成绑定的文本元素。如果你清除并重新发送元素,Excalidraw 可能重新注入其缓存的绑定文本,导致重复 - 清理步骤:
- 使用
query_elements/GET /api/elements查找type: "text"且带containerId的元素 - 使用
delete_element删除不需要的元素 - 等待几秒钟让自动同步稳定后再导出
- 使用
- 最安全的方法:绝不在背景区域矩形上放置标签 — 改用独立的文本元素
🎨 绘制流程(UI 原型图)
步骤 1:规划布局
在开始绘制前,必须说明布局规划:
布局规划:
- 画布尺寸:375×812 (移动端) 或 1200×800 (桌面端)
- 网格系统:8px 基准
- 主要区块:
1. 状态栏:0-44px (44px)
2. 顶部导航:44-100px (56px)
3. 搜索框:116-160px (44px,间距16px)
4. 轮播图:176-356px (180px,间距16px)
...
- 间距计算:验证所有间距符合规范
步骤 2:绘制背景和大区块
// 先绘制手机边框、状态栏、导航栏等大的背景块
{
"id": "phone-frame",
"type": "rectangle",
"x": 0,
"y": 0,
"width": 375,
"height": 812,
"backgroundColor": "#FFFFFF",
"strokeColor": "#1A1A1A",
"strokeWidth": 2,
"roughness": 0
}
步骤 3:绘制卡片和组件
// 批量创建卡片,确保:
// 1. 尺寸统一
// 2. 间距一致
// 3. 对齐网格
{
"elements": [
{"id": "card-1", "type": "rectangle", "x": 16, "y": 412, "width": 105, "height": 160, ...},
{"id": "card-2", "type": "rectangle", "x": 135, "y": 412, "width": 105, "height": 160, ...},
{"id": "card-3", "type": "rectangle", "x": 254, "y": 412, "width": 105, "height": 160, ...}
]
}
步骤 4:添加文字
// 文字放在矩形之后,确保 z-index 正确
{
"id": "card-title",
"type": "text",
"x": 26,
"y": 548,
"text": "电影标题",
"fontSize": 12,
"fontFamily": "2",
"strokeColor": "#1A1A1A",
"roughness": 0
}
步骤 5:截图验证
调用 get_canvas_screenshot 查看效果
运行质量检查清单 → 发现问题 → 调整
步骤 6:调整优化
如有问题,使用 update_element 调整:
- 位置不对:更新 x, y
- 尺寸不对:更新 width, height
- 颜色不对:更新 backgroundColor, strokeColor
- 文字不对:更新 text, fontSize
调整后再次截图验证,直到完美
❌ 常见错误与避免方法(UI 原型图)
错误 1:间距不一致
❌ 错误:
卡片1 间距 10px
卡片2 间距 15px
卡片3 间距 12px
✅ 正确:
所有卡片间距统一为 14px 或 16px
错误 2:卡片尺寸不统一
❌ 错误:
card-1: width=105, height=160
card-2: width=110, height=165
card-3: width=100, height=155
✅ 正确:
所有卡片 width=105, height=160
错误 3:未对齐网格
❌ 错误:
x=17, y=23(不是 4 的倍数)
✅ 正确:
x=16, y=24(都是 4 的倍数,优先 8 的倍数)
错误 4:文字太小
❌ 错误:
fontSize=8 或 fontSize=9
✅ 正确:
最小 fontSize=10,推荐 ≥12
错误 5:留白不足
❌ 错误:
卡片紧贴边框(边距 4-8px)
卡片间距 4-8px
✅ 正确:
移动端边距 16px
卡片间距 12-16px
区块间距 24-32px
错误 6:颜色混乱
❌ 错误:
使用 #FF0000(红色)、#0000FF(蓝色)
黑色深浅不一
✅ 正确:
仅使用规范中的黑白灰色阶
#1A1A1A、#333333、#666666、#999999、#CCCCCC、#E5E5E5、#F5F5F5、#FFFFFF
📚 参考文档
- cheatsheet.md: 完整的 MCP 工具列表(26 个工具)+ REST API 端点 + 负载格式
- wireframe-design-system.md: 完整的设计系统规范(色彩、间距、圆角、字体、组件)
- wireframe-components.md: 可复用的组件模板(JSON 代码)
- wireframe-quickstart.md: 5 分钟快速上手指南
- wireframe-skill-mcp-integration.md: Skill + MCP 结合使用指南