| name | ah-excalidraw-layout |
| description | Excalidraw 流程图排版引擎。输入结构化内容,输出零重叠的 Excalidraw 文件。
内嵌错题本规则,自动规避文字重叠/圆角挤压/容器撑破/箭头交叉等问题。
触发方式:/excalidraw、/画流程图、「帮我画Excalidraw」「用Excalidraw排版」「把这个做成图」
Not for: 自由绘图、手绘风格草图
|
ah-excalidraw-layout:Excalidraw 流程图排版引擎
你不是画图工具,你是排版引擎。每次排版前先读完本文件的错题本规则。所有规则来自真实翻车案例。
错题本(MUST READ FIRST)
错误 1:文字与图形重叠
- 错误:多个文字元素放在同一个
(x, y),或文字和矩形使用相同坐标但未绑定
- 正确:使用
box() 工厂函数自动绑定文字到矩形;独立文字必须确保距容器边框 >= 8px
错误 2:Group Frame 标签徽章与内部文字重叠
- 错误:在 group frame 边框上放置标签徽章(
y - 12),与内部标题重叠
- 正确:取消标签徽章。Group 标题作为框内首行文字,放在
y + PAD 位置
错误 3:容器使用固定高度
- 错误:
rect(x, y, w, 350) 硬编码高度
- 正确:
groupH = PAD + HEADER_H + 6 + items * (ITEM_H + ITEM_GAP) + PAD
错误 4:内容向右无限扩展
- 错误:传记卡片放在右侧边栏,总宽度超出屏幕
- 正确:所有内容纵向排列,最大宽度 900px。需要并排时最大两列,单列 <= 400px
错误 5:箭头交叉混乱
- 错误:左右两组各有独立箭头直接连向下一节点
- 正确:左右两组先汇聚到"汇总节点",再从汇总节点连向下一段
错误 6:大圆角挤压文字
- 错误:
roundness: { type: 3 }(大圆角)+ 文字贴近边框
- 正确:使用
{ type: 2 }(中小圆角),文字区相对边框内缩 >= 24px
错误 7:中文弯引号导致 JS 解析错误
- 错误:JS 双引号字符串内包含中文弯引号
""
- 正确:包含中文引号的字符串用单引号包裹,或替换为直角引号
「」
错误 8:同一卡片内不同内容区块无分隔
- 错误:传记卡片把基本信息和创作金句堆在一起
- 正确:不同区块之间加水平分隔线或 16px 以上空行
错误 9:不同体系的分组之间强行连线
- 错误:在两个独立体系的分组之间添加多条交叉虚线(如借势 pillars 和主角 pillars 之间 4 条 dot 连线)
- 正确:两个独立体系不需要在 pillar 级别建立关联。如果确实有关联,在更上层(汇总节点)统一交汇,不在细粒度节点之间拉线
错误 10:字体不统一 — 手写体与印刷体混用
- 错误:「AI 风口」「能力一」「能力二」等节点使用标准印刷字体(fontFamily: 2),与标题和正文的 Virgil 手写体(fontFamily: 1)风格割裂,像两套视觉系统拼在一起
- 发现轮次:第 7 轮(字体/边框/箭头/连线四维统一化调整)
- 正确:全图所有文字元素
fontFamily: 1(Virgil 手写体),生成后逐元素扫描确认无遗漏
- 自检:
grep -c '"fontFamily":2' 返回 0
错误 11:边框风格不统一 — 直角细边与圆角粗边混用
- 错误:顶部节点(如三风口框)使用
strokeWidth: 1 + 直角边框,下方色块使用 strokeWidth: 2 + roundness: {type: 2},视觉上像两套系统拼接
- 发现轮次:第 7 轮
- 正确:全图所有矩形统一
strokeWidth: 2、roundness: {type: 2}、strokeStyle: "solid"、roughness: 2
错误 12:箭头样式不统一 — 双线/单线/粗线/细线混用
- 错误:部分箭头是双线夹角样式,部分是普通细线箭头,部分是粗线,视觉噪音大
- 发现轮次:第 7 轮
- 正确:主流程箭头
strokeWidth: 1.5、辅助/汇聚箭头 strokeWidth: 1,全部使用 strokeStyle: "solid"、endArrowhead: "arrow"、startArrowhead: null,禁止双线或虚线样式
- 自检:所有 arrow 元素的
strokeStyle === "solid" 且 endArrowhead === "arrow"
错误 13:Mermaid 转换残留锚点 — 无意义的灰色控制点
- 错误:mermaid-to-excalidraw 转换器在多对多连接时自动插入 waypoint/anchor point(灰色圆点),这些不是有含义的内容节点,但视觉上看起来像"有东西"
- 发现轮次:第 5 轮(灰点/锚点/交叉线清理)
- 正确:直接生成 Excalidraw JSON 时(本 skill 的模式),永远不创建中间锚点。箭头路径为直接起点→终点,最多一次折弯
- 自检:不存在 type 非 arrow/rectangle/text 的中间节点
错误 14:文字溢出画布 — 节点宽度小于文字所需宽度
- 错误:节点设置了固定宽度,但文字行长度超出容器宽度,导致文字被截断或溢出到画布外
- 发现轮次:第 3 轮(文字溢出/分组重叠/连线交叉/宽度失控四合一)
- 正确:为每个节点计算所需宽度,公式:
nodeW = max(各文字行估算宽度) + 2 × PAD。中文字符估算 fontSize × 1.0 px,英文/数字估算 fontSize × 0.6 px
- 自检:对每个 rect+text 组合,检查文字最长行的估算宽度 <= rect.width - 2 × PAD
错误 15:连接线被分组边框遮盖 — z-index 顺序导致线条不可见
- 错误:细的连接线(strokeWidth 0.8-1.2)被粗的分组边框(strokeWidth 2+)压在下面,导致关键连线在视觉上消失
- 发现轮次:第 5 轮
- 正确:连接线元素在 JSON elements 数组中的位置必须排在所有分组框矩形之后(后渲染 = 在上层)。分组框 strokeWidth 不超过连接线 strokeWidth + 1.0
错误 16:连接线斜向交叉 — 左节点连右目标、右节点连左目标
- 错误:「真实案例」到「能力一/能力二」的连线斜向穿插,以及「汇合」到「怎么练/核心洞察」的橙色线和紫色线交叉
- 发现轮次:第 7 轮(四维统一化调整中的连线部分)
- 正确:左右一一对应路由 — 左侧来源 → 左侧目标,右侧来源 → 右侧目标。从左侧节点出发的箭头终点绝不出现在右侧节点上,反之亦然
- 自检:对每组并排节点,验证左侧组的箭头终点 x 坐标 < 页面中线,右侧组的箭头终点 x 坐标 > 页面中线
错误 17:container 绑定 ID 错位 — rect 和 text 互相引用不存在的 ID
- 错误:
box() 工厂函数使用 tid = rid() 生成一个 ID,然后 text(..., containerId=tid) 和 rect(..., boundElements=[tid])——但 text() 和 rect() 内部各自通过 rid() 生成自己的真实 id,tid 既不是 text 的 id 也不是 rect 的 id。结果:rect 的 boundElements 指向不存在的元素,text 的 containerId 指向不存在的容器。渲染出来是空壳矩形,文字消失或错位。
- 发现轮次:第 8 轮(2026-07-22 三棱镜定位法 Excalidraw 生成,用户发现橙色案例框内每行前面的圆角框是空的)
- 正确:禁止使用 containerId / boundElements 绑定。所有 text 和 rect 用绝对坐标分别放置,text 坐标 = rect 坐标 + 内边距偏移。如必须用工厂函数,函数必须返回并正确关联两个元素的真实 id。
- 自检:
grep -c '"containerId":null' 等于 text 元素总数;grep -c '"boundElements"' 返回 0
已验证模式(正例)
以下模式经 6 轮调试验证有效,生成时优先使用:
模式 1:游标推进布局
所有 y 坐标通过 curY 累进,禁止硬编码。每个 section 结束后 curY += sectionH + GAP。
模式 2:箭头汇聚路由
多来源 → 单汇总节点 → 下一段。禁止 N 条独立箭头从不同来源直接连向同一目标。
模式 3:左右一一对应路由(防交叉)
双列并排时,左侧列的箭头只连接左侧目标,右侧列只连接右侧目标。
模式 4:语义颜色体系
| 角色 | 主色 | 背景色 | 用于 |
|---|
| 核心主张 | #f08c00 | #ffec99 | 标题/论点/判断力 |
| AI/技术 | #1971c2 | #d0ebff / #e7f5ff | AI 能力/工具 |
| 案例/验证 | #2f9e44 | #d3f9d8 | 真实案例 |
| 终点/结论 | #e03131 | #ffc9c9 | 最终结论 |
| 洞察/升华 | #9c36b5 | #e599f7 | 核心洞察 |
| 训练/行动 | #e8590c | #ffe8cc | 怎么练/行动 |
| 历史/辅助 | #868e96 | #f8f9fa | 历史案例 |
| 汇聚标记 | #adb5bd | #e9ecef | 箭头汇聚节点 |
模式 5:节点宽度自适应公式
估算宽度 = 中文字符数 × fontSize × 1.0 + 英文/数字字符数 × fontSize × 0.6
nodeW = max(各行估算宽度) + 2 × PAD
模式 6:双列 + 单列混合布局
- 标题/核心主张/案例/终点 → 单列全宽,居中
- 对比项/并列能力/两个分支 → 双列并排
- 汇聚节点 → 窄条居中
质量检查清单(生成后逐项自检)
| # | 检查项 | 标准 | 对应错题 |
|---|
| 1 | 字体统一 | 所有 text 元素 fontFamily: 1 | #10 |
| 2 | 边框统一 | 所有 rect 元素 strokeWidth: 2, roundness.type: 2 | #11 |
| 3 | 箭头统一 | 所有 arrow 元素 strokeStyle: solid, endArrowhead: arrow | #12 |
| 4 | 无残留锚点 | 不存在 type 非 arrow/rectangle/text 的节点 | #13 |
| 5 | 文字不溢出 | 每行估算宽度 <= 容器宽度 - 2 × PAD | #14 |
| 6 | 连接线可见 | 连接线排在分组框之后 | #15 |
| 7 | 无交叉连线 | 左源→左目标,右源→右目标 | #16 |
| 8 | 容器自适应 | group frame 高度 = 计算值,无硬编码 | #3 |
| 9 | 内边距充足 | 文字距容器边框 >= 20px | #6 |
| 10 | 圆角安全 | roundness.type <= 2,文字区内缩 >= 24px | #6 |
| 11 | 引号安全 | JS 字符串无不匹配引号 | #7 |
| 12 | 区块分隔 | 不同内容区块间有分隔线或 16px+ 间距 | #8 |
| 13 | 宽度不超限 | max(x + width) <= 960 | #4 |
| 14 | 箭头先汇聚 | 多来源 → 单汇总 → 下一段 | #5 #9 |
| 15 | 无标签重叠 | Group 标题在框内首行,不在边框上 | #2 |
| 16 | 文字不重叠 | 非绑定文字元素各有独立坐标 | #1 |
| 17 | 无 container 绑定 | 所有 text.containerId = null,rect.boundElements 不存在 | #17 |
任一检查项未通过 → 回退修复对应元素,禁止带着缺陷交付。
排版规范
全局常量
PAD = 24 // 容器内边距
HEADER_H = 22 // 分组标题高度
GAP = 20 // 段间距
ITEM_GAP = 4 // 同组条目间距
MAX_W = 880 // 最大页面宽度
布局模式
- 单列全宽(标题、金句区、总结):PAGE_W = 880
- 双列并排(对比项、并列能力、两个分支):左列 LEFT_X = 60,右列 LEFT_X + 400,单列 COL_W = 380
游标推进
所有 y 坐标通过 curY 逐行累进,禁止硬编码:
curY = 30
section1: curY += h1 + GAP
section2: curY += h2 + GAP
颜色体系
| 用途 | 主色 | 背景色 |
|---|
| 借势 | #c92a2a | #fff5f5 |
| 主角 | #6741d9 | #f8f0ff |
| 金句/交汇 | #e8590c | #fff9db |
| 总结/启示 | #2b8a3e | #ebfbee |
| 生平/辅助 | #495057 | #f8f9fa |
完整语义颜色体系见上方「已验证模式 → 模式 4」。
箭头规范
- 主流程箭头:strokeWidth 1.5, strokeStyle solid, endArrowhead arrow
- 汇聚辅助箭头:strokeWidth 1.0, strokeStyle solid, endArrowhead arrow
- 禁止:双线夹角样式、虚线样式、startArrowhead(见错题 #12)
- 多来源先汇聚到单节点,再统一流向下段(见错题 #5 #9 #16)
迭代记录
v1.3.0:container 绑定 bug 修复(2026-07-22)
- 新增错题 #17:container 绑定 ID 错位
box() 工厂函数的 tid = rid() 模式被证明在 text() 和 rect() 各自生成内部 id 时无法正确关联
- 全局规则:禁止使用 containerId / boundElements,统一用绝对坐标定位
- 质量清单新增第 17 项检查
v1.2.0:错题本从 9 条扩至 16 条 + 新增正例模式库(2026-07-22)
来源:6 轮 Excalidraw 排版调试验证对话记录
对话覆盖的问题领域:
- Round 2:Mermaid 语法 → Excalidraw 转换原理
- Round 3:布局溢出四合一(文字溢出/分组重叠/连线交叉/宽度失控)
- Round 4:容器撑爆(固定高度/大圆角挤压/区块无分隔/标题贴边)
- Round 5:锚点清理(灰色 waypoint/连接线被遮盖/跨体系交叉)
- Round 7:四维统一化(字体/边框/箭头/连线风格不一致)
新增错题 7 条(#10-#16):
| # | 错误 | 根因 | 解决方案 |
|---|
| 10 | 字体不统一 | 部分节点使用印刷体 fontFamily:2 | 全图 fontFamily:1(Virgil 手写体) |
| 11 | 边框不统一 | 顶部用直角细边 vs 下方圆角粗边 | 统一 strokeWidth:2 + roundness.type:2 |
| 12 | 箭头不统一 | 双线/单线/粗线/细线混用 | 主流程 1.5 / 辅助 1.0 |
| 13 | Mermaid 残留锚点 | 转换器自动插入 waypoint | 直接生成 JSON 时不创建中间节点 |
| 14 | 文字溢出画布 | 节点宽度 < 文字所需宽度 | 宽度自适应公式 |
| 15 | 连接线被遮盖 | 分组框 strokeWidth 大于连接线 + z-index 在前 | 连接线排在分组框之后 |
| 16 | 连线斜向交叉 | 左源→右目标 / 右源→左目标 | 左右一一对应路由 |
新增正例(已验证模式 6 个):游标推进 / 箭头汇聚 / 左右对应 / 语义颜色 / 宽度自适应 / 混合布局
质量检查清单:从 9 项扩至 16 项,每项标注对应错题编号
v1.1.0:初版错题本(2026-07-22)
- 9 条错题:#1-#9(文字重叠/标签重叠/固定高度/无限右扩/箭头交叉/圆角挤压/引号错误/无分隔/跨体系连线)
- 排版规范、颜色体系、箭头规范初始版