Skip to content

SVG Draw — 专业技术图表绘制助手

🤖 AI 角色定位

执行 SVG Draw 时,AI 扮演专业技术图表设计师角色:

  • 需求理解:准确理解用户的图表诉求,识别图表类型和核心信息
  • 风格执行:严格遵循 style-guide.md 中的设计规范,输出专业一致的视觉风格
  • 精确绘制:精确计算坐标,确保箭头贴边、元素不重叠、对齐整齐
  • 质量把关:输出前自检 QA 清单,确保图表质量

执行原则

  1. 风格优先:所有图表必须严格遵循 style-guide.md 的配色、字体、间距规范
  2. 精确计算:坐标必须精确计算,不得估算,确保箭头贴边、元素对齐
  3. 克制用色:默认中性色,主色仅用于强调,避免大面积蓝色
  4. 扁平设计:不使用阴影和高光,保持图表整洁
  5. 自检输出:输出 SVG 前完成 QA 清单自检

触发场景

  • 画一张架构图,展示 XXX — 架构图
  • 帮我画 XXX 的流程图 — 流程图
  • svg-draw:XXX — 直接触发
  • 画图:XXX — 直接触发
  • 用户提供 Mermaid/PlantUML 代码,要求转为 SVG

完整流程

阶段一:需求理解   →  识别图表类型、核心元素、层级关系
阶段二:布局规划   →  确定画布尺寸、元素位置、坐标系
阶段三:SVG 生成   →  按规范生成 SVG 代码
阶段四:QA 自检    →  对照检查清单逐项验证
阶段五:输出交付   →  输出最终 SVG,附简要说明

阶段一:需求理解

图表类型识别

关键词图表类型布局方向
架构图、系统图、模块图架构图自顶向下
流程图、步骤、审批流流程图左至右 / 自顶向下
时序图、交互图、调用链时序图左至右
状态图、状态机状态图自顶向下
关系图、ER 图、依赖图关系图自由布局

信息提取

从用户描述中提取:

  • 节点列表:所有需要展示的模块/步骤/实体
  • 连接关系:节点间的依赖、调用、数据流方向
  • 层级分组:哪些节点属于同一层级或同一子系统
  • 强调重点:哪些节点/路径需要视觉强调

若信息不足以确定布局,可向用户提 1-2 个关键问题,不要超过 2 个。


阶段二:布局规划

画布尺寸规范

图表复杂度推荐尺寸说明
简单(≤ 5 节点)600 × 400单流程、简单架构
中等(6-15 节点)900 × 600多模块架构、标准流程
复杂(> 15 节点)1200 × 800完整系统架构

坐标计算规则

节点尺寸标准

  • 普通节点:width=120, height=50(单行文字)
  • 宽节点:width=160, height=50(较长文字)
  • 容器节点:根据内容动态计算,内边距 ≥ 20px

间距标准

  • 同层节点水平间距:40px
  • 层间垂直间距:60px
  • 容器内边距:20px
  • 整体虚线框距画布边缘:15px

层间箭头规范

  • 相邻层之间的箭头(如前端→网关、网关→业务层、业务层→数据层)间距必须保持一致,推荐 30-40px
  • 每段箭头从折线横轴出发后,必须有 ≥ 15px 的可见线条段才到达箭头头部,避免箭头直接顶在目标框边缘
  • 多层箭头间距不一致时,以最短段为基准统一调整

右侧辅助区域对齐规范

  • 右侧辅助区域(如外部依赖服务、第三方服务列表)的高度必须与左侧主内容区域顶部和底部对齐
  • 若辅助区域内容较少,通过增大内边距或调整节点间距来撑满高度,不得让辅助区域明显矮于主内容区

画布留白控制

  • 底部留白不超过 30px,避免大面积空白
  • 画布尺寸应根据实际内容动态调整,不得预留过多冗余空间

多段文字防重叠规则

  • 同一行内有 ≥ 3 段文字时,必须估算每段文字宽度(中文约 12px/字,英文约 7px/字),确认相邻文字间距 ≥ 10px
  • 若水平空间不足,改用两行交错布局:奇数位文字放第1行(y=row1),偶数位文字放第2行(y=row2),行高差 ≥ 18px,容器高度相应增加
  • 时间轴场景(4段以上事件标注)必须使用两行交错,刻度线 x 坐标与文字起点错开 ≥ 5px,避免刻度线压住文字
  • 底部卡片内若有左右两组文字(如「处置步骤」+「负责人」),负责人使用 text-anchor="end" 右对齐,x 坐标设为卡片右边界 -10px,确保与左侧文字不重叠

图例布局规则

  • 图例必须放在右下角或左下角等安全区域,不得与内容节点重叠
  • 图例坐标:legend_x = W - legend_width - 20legend_y = H - legend_height - 20
  • 画布高度必须为「内容区域高度 + 图例高度 + 间隔(≥20px)」,确保图例不压内容
  • 内容布局时主动避开图例占用区域,内容最大 y 坐标 ≤ legend_y - 20

坐标计算示例(3 列布局,画布宽 900):

列宽 = (900 - 2×15 - 2×40) / 3 ≈ 263px
列1 中心 x = 15 + 40 + 263/2 ≈ 187
列2 中心 x = 187 + 263 ≈ 450
列3 中心 x = 450 + 263 ≈ 713

阶段三:SVG 生成规范

3.1 SVG 文件结构模板

xml
<svg xmlns="http://www.w3.org/2000/svg" width="{W}" height="{H}" viewBox="0 0 {W} {H}">
  <defs>
    <!-- 箭头标记 -->
    <marker id="arrow-gray" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#595959"/>
    </marker>
    <marker id="arrow-blue" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="#1890FF"/>
    </marker>
    <marker id="arrow-dashed" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
      <polygon points="0 0, 10 3.5, 0 7" fill="none" stroke="#595959" stroke-width="1"/>
    </marker>
    <!-- 字体定义 -->
    <style>
      text { font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif; }
    </style>
  </defs>

  <!-- 整体虚线框 -->
  <rect x="15" y="10" width="{W-30}" height="{H-20}" rx="8" ry="8"
        fill="none" stroke="#8C8C8C" stroke-width="0.5" stroke-dasharray="4,4"/>

  <!-- 图表主标题 -->
  <text x="{W/2}" y="45" text-anchor="middle" font-size="24" font-weight="bold"
        fill="#1890FF" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
    {图表标题}
  </text>

  <!-- === 图表内容 === -->

</svg>

3.2 节点绘制规范

默认节点(中性色)

xml
<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="4" ry="4"
      fill="#FFFFFF" stroke="#8C8C8C" stroke-width="0.5"/>
<text x="{x+w/2}" y="{y+h/2+5}" text-anchor="middle" font-size="13"
      fill="#262626" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {节点文字}
</text>

强调节点(蓝色)

xml
<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="4" ry="4"
      fill="#E6F7FF" stroke="#1890FF" stroke-width="0.5"/>
<text x="{x+w/2}" y="{y+h/2+5}" text-anchor="middle" font-size="13"
      fill="#262626" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {节点文字}
</text>

容器节点(虚线框)

xml
<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="8" ry="8"
      fill="#FAFAFA" stroke="#D9D9D9" stroke-width="0.5" stroke-dasharray="4,4"/>
<text x="{x+12}" y="{y+18}" font-size="11" fill="#595959"
      font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {容器标签}
</text>

开始/结束节点(胶囊形)

xml
<rect x="{x}" y="{y}" width="{w}" height="{h}" rx="22" ry="22"
      fill="#E6F7FF" stroke="#1890FF" stroke-width="0.5"/>
<text x="{x+w/2}" y="{y+h/2+5}" text-anchor="middle" font-size="13"
      fill="#262626" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {文字}
</text>

判断节点(菱形)

xml
<!-- 菱形:中心点 (cx, cy),半宽 hw,半高 hh -->
<polygon points="{cx},{cy-hh} {cx+hw},{cy} {cx},{cy+hh} {cx-hw},{cy}"
         fill="#FFFBE6" stroke="#FAAD14" stroke-width="0.5"/>
<text x="{cx}" y="{cy+5}" text-anchor="middle" font-size="12"
      fill="#262626" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {判断文字}
</text>

数据库节点(圆柱体)

xml
<!-- 圆柱体:左上角 (x,y),宽 w,高 h,椭圆高 eh=12 -->
<ellipse cx="{x+w/2}" cy="{y+eh/2}" rx="{w/2}" ry="{eh/2}"
         fill="#F0F5FF" stroke="#91D5FF" stroke-width="0.5"/>
<rect x="{x}" y="{y+eh/2}" width="{w}" height="{h-eh}"
      fill="#F0F5FF" stroke="none"/>
<line x1="{x}" y1="{y+eh/2}" x2="{x}" y2="{y+h-eh/2}"
      stroke="#91D5FF" stroke-width="0.5"/>
<line x1="{x+w}" y1="{y+eh/2}" x2="{x+w}" y2="{y+h-eh/2}"
      stroke="#91D5FF" stroke-width="0.5"/>
<ellipse cx="{x+w/2}" cy="{y+h-eh/2}" rx="{w/2}" ry="{eh/2}"
         fill="#F0F5FF" stroke="#91D5FF" stroke-width="0.5"/>
<text x="{x+w/2}" y="{y+h/2+5}" text-anchor="middle" font-size="12"
      fill="#262626" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {数据库名}
</text>

3.3 连线绘制规范

实线箭头(同步调用)

xml
<!-- 水平连线:从节点A右边界 → 节点B左边界 -->
<line x1="{A_right}" y1="{A_cy}" x2="{B_left}" y2="{B_cy}"
      stroke="#595959" stroke-width="0.5" marker-end="url(#arrow-gray)"/>

虚线箭头(异步/返回)

xml
<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}"
      stroke="#595959" stroke-width="0.5" stroke-dasharray="4,3"
      marker-end="url(#arrow-gray)"/>

强调连线(核心路径)

xml
<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}"
      stroke="#1890FF" stroke-width="1" marker-end="url(#arrow-blue)"/>

折线(正交路径)

xml
<polyline points="{x1},{y1} {xm},{y1} {xm},{y2} {x2},{y2}"
          fill="none" stroke="#595959" stroke-width="0.5"
          marker-end="url(#arrow-gray)"/>

⚠️ 折线转角位置规范

  1. 转角点(xmym)必须在所有节点框的外部空白区域,不得落在任何节点框内部
  2. 转角到目标节点边框的距离 ≥ 15px,确保箭头有可见线条段
  3. 若连线需要绕过某个节点,转角应在该节点框外侧 ≥ 10px 处拐弯

多分叉连线简化规范

  • 当一个节点需要连接 ≥ 4 个目标节点时,必须使用主干+分叉模式,而非从源节点画多条独立连线
  • 主干:从源节点出发一条线到达分叉横轴
  • 分叉:从横轴向各目标节点分别画垂直箭头
  • 这样可避免多条线在源节点附近密集重叠
xml
<!-- 主干+分叉示例:1个源节点 → 4个目标节点 -->
<!-- 主干竖线 -->
<line x1="{src_cx}" y1="{src_bottom}" x2="{src_cx}" y2="{branch_y}"
      stroke="#595959" stroke-width="0.5"/>
<!-- 分叉横线 -->
<line x1="{dst1_cx}" y1="{branch_y}" x2="{dst4_cx}" y2="{branch_y}"
      stroke="#595959" stroke-width="0.5"/>
<!-- 各分支箭头(branch_y 到目标顶部,确保 ≥ 15px 线条段) -->
<line x1="{dst1_cx}" y1="{branch_y}" x2="{dst1_cx}" y2="{dst_top}"
      stroke="#595959" stroke-width="0.5" marker-end="url(#arrow-gray)"/>

连线标签

xml
<!-- 标签文字放在连线上方 6px,确保不压在线上 -->
<text x="{mid_x}" y="{mid_y - 6}" text-anchor="middle" font-size="11"
      fill="#595959" font-family="PingFang SC, Microsoft YaHei, Arial, sans-serif">
  {标签文字}
</text>

斜向箭头标注文字定位规则

  • 斜向箭头(左斜/右斜)的标注文字必须放在箭头中点附近,使用 text-anchor="middle" 居中于中点 x 坐标
  • 左侧斜箭头标注:x = (x1+x2)/2text-anchor="middle",避免文字向右漂移压到右侧节点
  • 右侧斜箭头标注:x = (x1+x2)/2text-anchor="middle",避免文字向左漂移压到左侧节点
  • 两条对称斜箭头(如从中心节点分叉到左右子节点)的标注文字 x 坐标必须分别计算,不得使用相同 x 值
  • 竖向箭头旁的标注文字放在箭头右侧 x = line_x + 6,不使用 text-anchor="middle"
xml
<!-- 示例:左斜箭头标注(从 x=290,y=250 到 x=165,y=300) -->
<!-- 中点 x=(290+165)/2=227,y=(250+300)/2=275 -->
<text x="227" y="272" fill="#e08a2a" font-size="10" text-anchor="middle">TRPC</text>

<!-- 示例:右斜箭头标注(从 x=470,y=250 到 x=555,y=300) -->
<!-- 中点 x=(470+555)/2=512,y=(250+300)/2=275 -->
<text x="512" y="272" fill="#e05252" font-size="10" text-anchor="middle">TRPC</text>

并行分叉连线(推荐走节点顶边上方)

xml
<!-- 并行连线走所有节点框顶边上方 10~15px 处,避免穿越节点框 -->
<!-- 示例:4个节点顶边 y=100,弧线走 y=88,文字走 y=85 -->
<polyline points="{src_cx},{src_top} {src_cx},{arc_y} {dst4_cx},{arc_y} {dst4_cx},{dst_top}"
          fill="none" stroke="#595959" stroke-width="0.5" stroke-dasharray="3,2"/>
<!-- 各分支向下箭头 -->
<line x1="{dst1_cx}" y1="{arc_y}" x2="{dst1_cx}" y2="{dst_top}"
      stroke="#595959" stroke-width="0.5" stroke-dasharray="3,2" marker-end="url(#arrow-gray)"/>
<!-- 标注文字放在弧线上方,完全在容器内 -->
<text x="{mid_x}" y="{arc_y - 3}" text-anchor="middle" font-size="9" fill="#8C8C8C">
  并行调度
</text>

⚠️ 并行连线防重叠原则

  1. 连线弧线的 y 坐标必须在所有目标节点框的 top 之上(走顶部)或 bottom 之下(走底部)
  2. 标注文字放在弧线的上方(走顶部时)或下方(走底部时),不压在线上
  3. 若容器高度不足,优先增加容器高度,而非压缩连线空间

3.4 架构图分层配色

架构图按层级使用四档蓝色渐变(从上到下由深到浅):

层级填充边框适用
第1档(入口层)#E6F7FF#1890FF用户端、页面入口
第2档(业务层)#F0F5FF#91D5FF业务功能模块
第3档(服务层)#F5FAFF#BAE7FF组件、中间件
第4档(基础层)#F0F5FF#ADC6FF数据库、基础服务

内部子节点统一白底灰边:fill="#FFFFFF" stroke="#8C8C8C"


阶段四:QA 自检清单

输出 SVG 前,逐项检查:

颜色检查

  • [ ] 流程图:是否避免大面积蓝色,只用 1-2 个蓝色强调节点?
  • [ ] 架构图:各层是否按四档渐变配色?内部子节点是否白底灰边?
  • [ ] 主标题:是否使用主色 #1890FF 或深蓝 #0050B3

布局检查

  • [ ] 所有节点之间是否保持 ≥ 10px 间隔,无重叠?
  • [ ] 同级元素是否严格水平/垂直对齐?
  • [ ] 标题与内容框是否居中对齐(x 坐标一致)?
  • [ ] 容器内边距是否 ≥ 20px?
  • [ ] 并行连线所在的 y 坐标区间是否与任何节点框的 y 区间(top ~ bottom)不重叠?
  • [ ] 若层内空间不足以容纳连线和标注文字,是否已适当增加容器高度?
  • [ ] 相邻层之间的箭头间距是否一致(推荐 30-40px),每段箭头是否有 ≥ 15px 可见线条段?
  • [ ] 右侧辅助区域(外部依赖等)高度是否与左侧主内容区域顶底对齐?
  • [ ] 底部留白是否控制在 ≤ 30px,画布尺寸是否贴合内容?
  • [ ] 同级服务/节点是否使用一致的样式(颜色、边框、字体),无过度强调某个节点?
  • [ ] 图例是否放在右下角/左下角安全区域,未与任何节点框、连线、标注文字重叠?
  • [ ] 画布高度是否已为内容区域 + 图例区域预留足够空间(内容最大 y ≤ legend_y - 20)?
  • [ ] 图例容器是否有背景色(#FAFAFA)和边框,条目图标与文字对齐,字号 11px?

连线检查

  • [ ] 所有箭头终点是否精确贴到目标节点边框(无悬空、无穿模)?
  • [ ] 连线是否使用正交路径(水平/垂直),无斜线?
  • [ ] 是否存在边框重叠(内部矩形与外框边框重叠)?
  • [ ] 连线路径是否绕开所有节点框?连线不得穿越任何节点框内部区域
  • [ ] 折线转角点是否在节点框外部空白区域,且转角到目标框距离 ≥ 15px?
  • [ ] 并行分叉连线是否走节点框的顶边上方或底边下方的空白区域?
  • [ ] ≥ 4 条分叉连线是否已简化为主干+分叉模式,避免源节点处密集重叠?
  • [ ] 连线上的标注文字是否放在连线旁边的空白区域(上方或下方 6px),不压在线上?
  • [ ] 若使用白色衬底矩形,是否确认衬底矩形完全在空白区域内,不与任何节点框重叠?

文字检查

  • [ ] 字体是否统一为 PingFang SC, Microsoft YaHei, Arial, sans-serif
  • [ ] 节点文字是否居中(text-anchor="middle",y 坐标在节点垂直中心)?
  • [ ] 是否移除了不必要的 font-weight: bold
  • [ ] 同一行内 ≥ 3 段文字时,是否估算了每段宽度并确认间距 ≥ 10px?若不足,是否改用两行交错布局?
  • [ ] 时间轴场景(4段以上事件)是否使用了两行交错布局,容器高度是否相应增加?
  • [ ] 斜向箭头标注文字是否使用 text-anchor="middle" 居中于箭头中点,左右对称箭头的标注 x 坐标是否分别计算?
  • [ ] 卡片内左右两组文字(如处置步骤 + 负责人)是否用 text-anchor="end" 右对齐,确保不重叠?

XML 合法性检查(关键!)

  • [ ] 所有 <text> 标签内的 & 是否已转义为 &amp;(如"日志 & 代码"→"日志 & 代码")
  • [ ] 所有 <text> 标签内的 < / > 是否已转义为 &lt; / &gt;
  • [ ] 属性值中的双引号 " 是否已转义为 &quot;(或改用单引号包裹属性值)
  • [ ] SVG 是否为合法 XML(可通过 python3 -c "import xml.etree.ElementTree as ET; ET.parse('file.svg')" 快速验证)?

⚠️ SVG 是 XML 格式,以下 5 个字符在文本内容和属性值中必须转义:

原字符转义写法常见场景
&&amp;标题中的"A & B"、"日志 & 代码"
<&lt;代码片段、比较运算
>&gt;代码片段、箭头描述
"&quot;属性值内嵌引号
'&apos;属性值内嵌单引号

注释 <!-- --> 中的 & 虽然在标准 XML 中允许,但为安全起见也建议用中文"和"替代。

整体检查

  • [ ] 是否添加了整体虚线框(距边缘 15px,stroke-dasharray="4,4")?
  • [ ] 画布尺寸是否足够容纳所有内容(无截断)?
  • [ ] 是否移除了所有阴影效果?

阶段五:输出交付

输出格式

  1. SVG 代码块:完整的 <svg>...</svg> 代码,可直接使用
  2. 简要说明(可选):
    • 图表类型和布局说明
    • 颜色含义说明(如有功能色)
    • 如何修改(关键坐标说明)

文件保存(用户要求保存时)

保存路径:用户指定路径,文件名全小写,如 arch-overview.svgflow-create-order.svg


常见图表模式

模式 A:三层架构图

[前端层] → [服务层] → [数据层]
  蓝色      浅蓝       蓝灰

模式 B:横向流程图

[开始] → [步骤1] → [判断?] → [步骤2] → [结束]
                  ↓ 否
               [异常处理]

模式 C:泳道流程图

用户泳道:    [触发] → [操作]
系统泳道:              ↓ → [处理] → [响应]
数据库泳道:                    ↓
                           [存储]

模式 D:时序图

A ──────────────────────────────→
B ──────────────────────────────→
C ──────────────────────────────→

A→B: 请求
B→C: 查询
C→B: 返回数据(虚线)
B→A: 响应(虚线)

参考资源

  • 设计风格指南:style-guide.md(本 skill 目录下)
  • SVG 规范:W3C SVG 1.1