excalidraw
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExcalidraw Diagram Generation
Excalidraw 图表生成
Generate professional hand-drawn style diagrams in Excalidraw JSON format.
生成专业手绘风格的Excalidraw JSON格式图表。
Critical Rules
核心规则
-
Arrow Binding (MUST follow): Arrows must bind to components bidirectionally:
- Arrow needs and
startBindingpointing to component IDsendBinding - Rectangle needs array listing bound arrow IDs
boundElements - Without both, arrows won't snap to components
- Arrow needs
-
Text requires width/height: Text elements must haveand
widthfields, otherwise they won't renderheight -
Arrow labels: Place below arrow (y + 30) or above (y - 30), never overlapping components
-
Background region sizing (MUST follow): Background regions (subgraphs/phases) must fully cover all contained elements:
- Calculate bounding box: find min/max x/y of ALL elements in the region
- Add padding: 40px on all sides
- Formula: ,
width = (maxX + maxWidth) - minX + 80height = (maxY + maxHeight) - minY + 80 - Verify: every child element's bottom-right corner must be inside the region
-
No overlaps (MUST follow): Arrows must not cross unrelated components; labels must not overlap components. See "Layout Optimization" section for strategies.
-
Container binding (MUST follow): When connecting to grouped/nested structures, arrows must bind to the outer container (background region), NOT to internal elements:
- If a phase/subgraph contains multiple internal steps, arrows from outside should connect to the container box
- Internal element connections stay internal; external connections go to the container
- Example: (container), NOT
dag → main-bg(internal element)dag → read-main - This keeps the diagram semantically correct and visually clean
-
Sibling layout (MUST follow): Elements at the same hierarchy level must be placed horizontally (same row), NOT vertically:
- Siblings represent parallel/alternative paths (e.g., TCP and HTTP handlers)
- Vertical stacking implies sequential execution, which is semantically wrong for siblings
- Use fork arrows from parent to horizontally-aligned children
-
Nested structure clarity (MUST follow): When a container has internal elements, ensure clear hierarchy and no overlaps:
- Internal elements must have proper vertical spacing with arrows showing call sequence
- Text labels must fit entirely within their rectangles (calculate: )
rect.height >= text.height + 20 - Reference annotations (file paths, line numbers) go OUTSIDE the box (below or to the right)
- Sub-containers within a parent should be visually distinct (different opacity or color shade)
-
Arrow path space reservation (MUST follow): When arrows connect nested containers, ensure sufficient space for arrow routing:
- Problem: If containers are too close, arrows may pass through target containers instead of connecting to their edges
- Solution: Proactively enlarge parent containers to leave 40-60px gap between child containers and the next target
- When multiple sub-containers need to merge arrows to a shared target below, calculate:
target.y >= max(child.y + child.height) + 60 - If arrow crossing occurs after generation, increase container heights rather than using complex bypass paths
-
箭头绑定(必须遵守):箭头必须与组件双向绑定:
- 箭头需包含和
startBinding字段,指向对应组件IDendBinding - 矩形组件需包含数组,列出绑定的箭头ID
boundElements - 缺少任意一项,箭头都无法吸附到组件上
- 箭头需包含
-
文本元素需指定宽高:文本元素必须包含和
width字段,否则无法渲染height -
箭头标签位置:箭头标签需放置在箭头下方(y坐标+30)或上方(y坐标-30),禁止与组件重叠
-
背景区域尺寸(必须遵守):背景区域(子图/阶段)必须完全覆盖其包含的所有元素:
- 计算边界框:找出区域内所有元素的最小/最大x/y坐标
- 添加内边距:四边各留40px
- 计算公式:,
width = (maxX + maxWidth) - minX + 80height = (maxY + maxHeight) - minY + 80 - 验证:确保每个子元素的右下角都在区域内部
-
禁止重叠(必须遵守):箭头不得穿过无关组件;标签不得与组件重叠。可参考「布局优化」章节的解决策略。
-
容器绑定(必须遵守):连接分组/嵌套结构时,箭头必须绑定到外部容器(背景区域),而非内部元素:
- 如果某个阶段/子图包含多个内部步骤,外部箭头应连接到容器框
- 内部元素的连接保持在容器内部;外部连接仅指向容器
- 示例:(容器),而非
dag → main-bg(内部元素)dag → read-main - 这样可保证图表语义正确且视觉整洁
-
同级元素布局(必须遵守):同一层级的元素必须水平排列(同一行),不得垂直堆叠:
- 同级元素代表并行/可选路径(如TCP和HTTP处理器)
- 垂直堆叠会暗示顺序执行,这对同级元素来说语义错误
- 使用分叉箭头从父元素指向水平排列的子元素
-
嵌套结构清晰度(必须遵守):当容器包含内部元素时,需确保层级清晰且无重叠:
- 内部元素间需保留适当垂直间距,并用箭头表示调用顺序
- 文本标签必须完全适配其所在矩形(计算公式:)
rect.height >= text.height + 20 - 参考注释(文件路径、行号)需放在框外(下方或右侧)
- 父容器内的子容器需视觉区分(不同透明度或色调)
-
箭头路径空间预留(必须遵守):当箭头连接嵌套容器时,需为箭头路由预留足够空间:
- 问题:如果容器间距过近,箭头可能穿过目标容器而非连接到其边缘
- 解决方案:主动放大父容器,在子容器与下一个目标之间留出40-60px间隙
- 当多个子容器需要将箭头合并到下方共享目标时,计算公式:
target.y >= max(child.y + child.height) + 60 - 如果生成后仍出现箭头交叉,优先增加容器高度,而非使用复杂的绕行路径
Mandatory Workflow (MUST follow before writing JSON)
强制工作流(编写JSON前必须遵守)
Step 1: Arrow Path Analysis
Before placing any component, list ALL arrows and their source→target pairs:
Arrow 1: A → B (horizontal)
Arrow 2: B → C (horizontal)
Arrow 3: C → A (return arrow - DANGER: will cross B if horizontal layout)Step 2: Identify Crossing Risks
For each arrow, check: "Does a straight line from source to target pass through any other component?"
- If YES → mark as "needs layout adjustment" or "needs bypass path"
- Common patterns that cause crossings:
- Return arrows in horizontal layouts (e.g., C → A when B is between them)
- Bidirectional flows between non-adjacent components
- Hub-and-spoke patterns with central component
Step 3: Choose Layout Strategy
Based on crossing risks, select appropriate layout:
- No crossings: Use simple horizontal/vertical layout
- 1-2 crossings: Use bypass paths (multi-point arrows)
- 3+ crossings or complex flows: Restructure to 2D layout (grid, triangle, diamond)
Step 4: Verify Before Finalizing
After generating JSON, mentally trace each arrow path and confirm:
- No arrow passes through any component it doesn't connect to
- No label overlaps any component
- All background regions fully contain their elements
步骤1:箭头路径分析
在放置任何组件前,列出所有箭头及其源→目标对:
Arrow 1: A → B (horizontal)
Arrow 2: B → C (horizontal)
Arrow 3: C → A (return arrow - DANGER: will cross B if horizontal layout)步骤2:识别交叉风险
对每个箭头,检查:「从源到目标的直线是否会穿过其他组件?」
- 如果是 → 标记为「需要调整布局」或「需要绕行路径」
- 常见的交叉风险场景:
- 水平布局中的返回箭头(如B在A和C之间时,C→A的箭头)
- 非相邻组件间的双向流
- 中心组件的星型连接模式
步骤3:选择布局策略
根据交叉风险,选择合适的布局:
- 无交叉:使用简单的水平/垂直布局
- 1-2处交叉:使用绕行路径(多点箭头)
- 3处及以上交叉或复杂流:重构为2D布局(网格、三角形、菱形)
步骤4:最终验证
生成JSON后,逐一追踪每个箭头路径并确认:
- 箭头未穿过任何非关联组件
- 标签未与任何组件重叠
- 所有背景区域完全包含其内部元素
Core Elements
核心元素
Base Template
基础模板
json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [],
"appState": { "viewBackgroundColor": "#ffffff" },
"files": {}
}json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [],
"appState": { "viewBackgroundColor": "#ffffff" },
"files": {}
}Element Templates
元素模板
Rectangle (Component Box)
json
{
"id": "unique-id",
"type": "rectangle",
"x": 100, "y": 100,
"width": 140, "height": 60,
"strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff",
"roundness": { "type": 3 },
"boundElements": [{"id": "arrow-id", "type": "arrow"}]
}Text (width/height required, fontFamily: 4 required)
json
{
"id": "unique-id",
"type": "text",
"x": 120, "y": 120,
"width": 80, "height": 24,
"text": "Label",
"fontSize": 16,
"fontFamily": 4,
"textAlign": "center"
}Text centering formula (to center text inside a rectangle):
text.x = rect.x + (rect.width - text.width) / 2text.y = rect.y + (rect.height - text.height) / 2
Arrow
json
{
"id": "unique-id",
"type": "arrow",
"x": 240, "y": 130,
"points": [[0, 0], [100, 0]],
"startBinding": { "elementId": "source-id", "focus": 0, "gap": 5 },
"endBinding": { "elementId": "target-id", "focus": 0, "gap": 5 },
"endArrowhead": "arrow"
}Arrow coordinate system:
- ,
x: absolute position of arrow start pointy - : relative offsets from (x, y). First point is always [0, 0]
points - Example: draws L-shaped arrow starting at (100, 200)
x: 100, y: 200, points: [[0,0], [50, 0], [50, 100]]
Background Region - Use rectangle with
"opacity": 30矩形(组件框)
json
{
"id": "unique-id",
"type": "rectangle",
"x": 100, "y": 100,
"width": 140, "height": 60,
"strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff",
"roundness": { "type": 3 },
"boundElements": [{"id": "arrow-id", "type": "arrow"}]
}文本(必须指定宽高,必须使用fontFamily: 4)
json
{
"id": "unique-id",
"type": "text",
"x": 120, "y": 120,
"width": 80, "height": 24,
"text": "Label",
"fontSize": 16,
"fontFamily": 4,
"textAlign": "center"
}文本居中公式(使文本在矩形内居中):
text.x = rect.x + (rect.width - text.width) / 2text.y = rect.y + (rect.height - text.height) / 2
箭头
json
{
"id": "unique-id",
"type": "arrow",
"x": 240, "y": 130,
"points": [[0, 0], [100, 0]],
"startBinding": { "elementId": "source-id", "focus": 0, "gap": 5 },
"endBinding": { "elementId": "target-id", "focus": 0, "gap": 5 },
"endArrowhead": "arrow"
}箭头坐标系:
- ,
x: 箭头起点的绝对位置y - : 相对于(x, y)的偏移量。第一个点始终为[0, 0]
points - 示例:绘制从(100, 200)开始的L形箭头
x: 100, y: 200, points: [[0,0], [50, 0], [50, 100]]
背景区域 - 使用设置了的矩形
"opacity": 30Default Values (can be omitted)
可省略的默认值
json
"fillStyle": "solid", "strokeWidth": 2, "roughness": 1,
"opacity": 100, "angle": 0, "seed": 1, "version": 1json
"fillStyle": "solid", "strokeWidth": 2, "roughness": 1,
"opacity": 100, "angle": 0, "seed": 1, "version": 1Color System
配色系统
| Purpose | Background | Stroke |
|---|---|---|
| Primary / Phase 1 | | |
| Secondary / Phase 2 | | |
| Accent / Shared | | |
| Storage / State | | |
| 用途 | 背景色 | 描边色 |
|---|---|---|
| 主要/阶段1 | | |
| 次要/阶段2 | | |
| 强调/共享 | | |
| 存储/状态 | | |
Layout Rules
布局规则
- Align coordinates to multiples of 20
- Component spacing: 100-150px
- Standard component size:
140×60 - Background regions:
opacity: 30 - Render order: earlier elements in array appear behind
- 坐标对齐到20的倍数
- 组件间距:100-150px
- 标准组件尺寸:
140×60 - 背景区域:
opacity: 30 - 渲染顺序:数组中靠前的元素显示在底层
Common Diagram Patterns
常见图表模式
Sequence Diagram Layout
序列图布局
For sequence diagrams (multiple participants with message flows):
- Place participants horizontally at top (y = 100)
- Each phase/stage gets its own vertical section below
- Use background regions to separate phases
- Vertical lifelines are implicit (not drawn as elements)
- Messages flow left-to-right or right-to-left between participants
Layout strategy:
Phase 1 (y: 80-300): [A] -----> [B] -----> [C]
msg1 msg2
[A] <----- [B]
response
Phase 2 (y: 320-500): [A'] ----> [B'] ----> [C']
(duplicate participants at new y)Key insight: For multi-phase sequence diagrams, duplicate participant boxes in each phase rather than drawing long vertical lifelines. This avoids arrow crossing issues.
对于包含多个参与者和消息流的序列图:
- 参与者水平排列在顶部(y = 100)
- 每个阶段/步骤在下方拥有独立的垂直区域
- 使用背景区域分隔不同阶段
- 垂直生命线为隐式(不绘制为元素)
- 消息在参与者之间左右流动
布局策略:
Phase 1 (y: 80-300): [A] -----> [B] -----> [C]
msg1 msg2
[A] <----- [B]
response
Phase 2 (y: 320-500): [A'] ----> [B'] ----> [C']
(在新y坐标处复制参与者)关键技巧:对于多阶段序列图,在每个阶段复制参与者框,而非绘制长垂直生命线。这可避免箭头交叉问题。
Layout Optimization (Avoiding Overlaps)
布局优化(避免重叠)
Prevent Arrow Overlap
防止箭头重叠
When multiple arrows connect to the same component:
- Use parameter to offset arrow positions on component edge
focus - = upper half,
focus: -0.5= lower half,focus: 0.5= centerfocus: 0 - Example: two horizontal arrows can use and
focus: -0.5to separate verticallyfocus: 0.5
当多个箭头连接到同一组件时:
- 使用参数偏移箭头在组件边缘的位置
focus - = 上半部分,
focus: -0.5= 下半部分,focus: 0.5= 中心focus: 0 - 示例:两个水平箭头可分别使用和
focus: -0.5实现垂直分隔focus: 0.5
Prevent Arrows Crossing Components
防止箭头穿过组件
When arrows would cross unrelated components, restructure the layout:
3 components with return arrow (A→B→C, C→A):
- Triangle layout: A at top, B bottom-left, C bottom-right
- All arrows flow along triangle edges, no crossings
4 components with return arrow (A→B→C→D, D→A):
- Diamond layout: A at top, B left, C bottom, D right
- Or 2×2 grid with diagonal return arrow
- Or use bypass path for return arrow (route above/below the row)
4+ components in sequence with return arrows:
- Split into rows: forward flow on top row, return flow on bottom row
- Or use vertical bypass: return arrows route above/below all components
json
"points": [[0, 0], [0, -80], [-400, -80], [-400, 0]]
Hub-and-spoke (central component connects to many):
- Place hub in center, spokes radially around it
- Avoid placing spokes in a line with hub in middle
Default assumption: If there's a return arrow, horizontal layout will likely fail—plan for bypass or 2D layout upfront.
当箭头会穿过无关组件时,重构布局:
带返回箭头的3个组件(A→B→C,C→A):
- 三角形布局:A在顶部,B在左下,C在右下
- 所有箭头沿三角形边缘流动,无交叉
带返回箭头的4个组件(A→B→C→D,D→A):
- 菱形布局:A在顶部,B在左侧,C在底部,D在右侧
- 或2×2网格布局,搭配对角线返回箭头
- 或为返回箭头使用绕行路径(在所有组件上方/下方路由)
json
"points": [[0, 0], [0, -80], [-400, -80], [-400, 0]]
4个以上组件的序列带返回箭头:
- 拆分为两行:正向流在上行,返回流在下行
- 或使用垂直绕行:返回箭头在所有组件上方/下方路由
星型连接(中心组件连接多个其他组件):
- 将中心组件放在中间,其他组件呈放射状环绕
- 避免将组件排成直线,中心组件在中间
默认假设:如果存在返回箭头,水平布局很可能失效——提前规划绕行路径或2D布局。
Complete Example
完整示例
Flow with Return Arrow (using bypass path)
A → B → C, then C → A (return arrow routes above to avoid crossing B)
Arrow analysis:
- Arrow 1: A → B (horizontal) ✓
- Arrow 2: B → C (horizontal) ✓
- Arrow 3: C → A (return) ⚠️ Would cross B → use bypass path above
json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id": "a", "type": "rectangle", "x": 100, "y": 150, "width": 140, "height": 60, "backgroundColor": "#a5d8ff", "strokeColor": "#1971c2", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "a-label", "type": "text", "x": 155, "y": 168, "width": 30, "height": 24, "text": "A", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "b", "type": "rectangle", "x": 340, "y": 150, "width": 140, "height": 60, "backgroundColor": "#b2f2bb", "strokeColor": "#2f9e44", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr2", "type": "arrow"}]},
{"id": "b-label", "type": "text", "x": 395, "y": 168, "width": 30, "height": 24, "text": "B", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "c", "type": "rectangle", "x": 580, "y": 150, "width": 140, "height": 60, "backgroundColor": "#d0bfff", "strokeColor": "#7048e8", "roundness": {"type": 3}, "boundElements": [{"id": "arr2", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "c-label", "type": "text", "x": 635, "y": 168, "width": 30, "height": 24, "text": "C", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "arr1", "type": "arrow", "x": 245, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "a", "focus": 0, "gap": 5}, "endBinding": {"elementId": "b", "focus": 0, "gap": 5}},
{"id": "arr2", "type": "arrow", "x": 485, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "b", "focus": 0, "gap": 5}, "endBinding": {"elementId": "c", "focus": 0, "gap": 5}},
{"id": "arr3", "type": "arrow", "x": 650, "y": 145, "points": [[0, 0], [0, -60], [-480, -60], [-480, 0]], "endArrowhead": "arrow", "strokeStyle": "dashed", "startBinding": {"elementId": "c", "focus": 0, "gap": 5}, "endBinding": {"elementId": "a", "focus": 0, "gap": 5}},
{"id": "arr3-label", "type": "text", "x": 380, "y": 60, "width": 60, "height": 20, "text": "return", "fontSize": 12, "fontFamily": 4, "textAlign": "center"}
],
"appState": {"viewBackgroundColor": "#ffffff"},
"files": {}
}带返回箭头的流程(使用绕行路径)
A → B → C,然后C → A(返回箭头从上方绕行以避开B)
箭头分析:
- 箭头1:A → B(水平) ✓
- 箭头2:B → C(水平) ✓
- 箭头3:C → A(返回) ⚠️ 会穿过B → 使用上方绕行路径
json
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{"id": "a", "type": "rectangle", "x": 100, "y": 150, "width": 140, "height": 60, "backgroundColor": "#a5d8ff", "strokeColor": "#1971c2", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "a-label", "type": "text", "x": 155, "y": 168, "width": 30, "height": 24, "text": "A", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "b", "type": "rectangle", "x": 340, "y": 150, "width": 140, "height": 60, "backgroundColor": "#b2f2bb", "strokeColor": "#2f9e44", "roundness": {"type": 3}, "boundElements": [{"id": "arr1", "type": "arrow"}, {"id": "arr2", "type": "arrow"}]},
{"id": "b-label", "type": "text", "x": 395, "y": 168, "width": 30, "height": 24, "text": "B", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "c", "type": "rectangle", "x": 580, "y": 150, "width": 140, "height": 60, "backgroundColor": "#d0bfff", "strokeColor": "#7048e8", "roundness": {"type": 3}, "boundElements": [{"id": "arr2", "type": "arrow"}, {"id": "arr3", "type": "arrow"}]},
{"id": "c-label", "type": "text", "x": 635, "y": 168, "width": 30, "height": 24, "text": "C", "fontSize": 16, "fontFamily": 4, "textAlign": "center"},
{"id": "arr1", "type": "arrow", "x": 245, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "a", "focus": 0, "gap": 5}, "endBinding": {"elementId": "b", "focus": 0, "gap": 5}},
{"id": "arr2", "type": "arrow", "x": 485, "y": 180, "points": [[0, 0], [90, 0]], "endArrowhead": "arrow", "startBinding": {"elementId": "b", "focus": 0, "gap": 5}, "endBinding": {"elementId": "c", "focus": 0, "gap": 5}},
{"id": "arr3", "type": "arrow", "x": 650, "y": 145, "points": [[0, 0], [0, -60], [-480, -60], [-480, 0]], "endArrowhead": "arrow", "strokeStyle": "dashed", "startBinding": {"elementId": "c", "focus": 0, "gap": 5}, "endBinding": {"elementId": "a", "focus": 0, "gap": 5}},
{"id": "arr3-label", "type": "text", "x": 380, "y": 60, "width": 60, "height": 20, "text": "return", "fontSize": 12, "fontFamily": 4, "textAlign": "center"}
],
"appState": {"viewBackgroundColor": "#ffffff"},
"files": {}
}Output
输出
- Filename:
{descriptive-name}.excalidraw.json - Location: project root or folder
docs/ - Tell user: drag into https://excalidraw.com or open with VS Code Excalidraw extension
- 文件名:
{descriptive-name}.excalidraw.json - 位置:项目根目录或文件夹
docs/ - 告知用户:可拖拽到https://excalidraw.com 或使用VS Code Excalidraw扩展打开
Notes
注意事项
- IDs must be unique across the file
- : 1=Virgil, 2=Helvetica, 3=Cascadia, 4=Comic Shanns (MUST use for hand-drawn style)
fontFamily - usage in software diagrams:
strokeWidth- (thin): background regions, container borders, secondary connections
1 - (normal/default): primary components, main flow arrows
2 - (bold): emphasis, critical paths, highlighted elements
4
- Dashed arrows: add
"strokeStyle": "dashed"
- 整个文件中的ID必须唯一
- :1=Virgil,2=Helvetica,3=Cascadia,4=Comic Shanns(手绘风格必须使用此选项)
fontFamily - 软件图中的使用:
strokeWidth- (细):背景区域、容器边框、次要连接
1 - (正常/默认):主要组件、主流程箭头
2 - (粗):强调、关键路径、高亮元素
4
- 虚线箭头:添加
"strokeStyle": "dashed"