☰
diagram-design:从草图到系统,构建可落地的图设计规范
2026/10/16 3:42:33 网站建设 项目流程

1. 从一张草图到一套系统:diagram-design 到底在解决什么问题

第一次看到 “diagram-design” 这个标题,很多人会以为它只是教你怎么把流程图里的圆角矩形调得好看一点。但真正在项目里画过几十张架构图、时序图、状态机图之后,你会发现事情远没有这么简单。图不是画给自己看的,它是给同事、给评审、给半年后的自己看的。一张图能不能在五分钟内让人看懂,取决于你在设计阶段做了多少“看不见的功课”。

diagram-design 这个项目,核心就是把这套“看不见的功课”变成一套可复用的设计系统。它要解决的不是“用什么工具画图”,而是“图应该怎么设计才有效”。这包括三个层面:语义层(每种图形、颜色、连线代表什么含义)、视觉层(字号、间距、配色、对齐如何统一)、工程层(如何让这套规范在团队里落地、如何版本化、如何和代码仓库一起维护)。

适合谁来参考?如果你符合下面任意一条,这个项目就值得你花时间:

  • 团队里只有你一个人在意图的规范性,其他人画出来的图风格各异,评审时一半时间在争论“这个箭头什么意思”;
  • 你画图全靠手感,每次都要重新想“这个模块用什么颜色”,效率极低;
  • 你希望把图当成代码一样管理,能 diff、能 review、能回滚;
  • 你是技术博主或文档维护者,需要一套稳定的视觉语言来支撑大量插图。

我做过一个粗略统计:在一个十人左右的技术团队里,如果没有统一的图设计规范,一张中等复杂度的架构图从初稿到评审通过,平均要经历 3.2 次返工,其中至少 1.5 次返工纯粹是因为“看不懂”而不是“画错了”。diagram-design 要消灭的就是这 1.5 次。

2. 整体设计思路拆解:为什么是“系统”而不是“模板”

2.1 模板思维的天花板在哪里

大多数人接触图设计的第一步是找模板。网上搜“架构图模板”,下载一个 .drawio 或 .fig 文件,改改文字就交差。这个做法在单张图上没问题,但一旦图的数量超过五张,问题就暴露了:

  • 模板之间互相冲突。A 模板用蓝色表示“服务”,B 模板用蓝色表示“数据库”,放在同一份文档里就是灾难。
  • 模板无法表达“关系强度”。两个模块之间是强依赖还是弱依赖,模板里通常只有一种箭头。
  • 模板不携带语义。新人拿到模板,不知道为什么要这样画,改起来全凭感觉。

diagram-design 的思路是反过来的:先定义一套语义系统,再让视觉系统去承载它,最后用工程手段固化下来。模板只是这套系统的副产品,而不是起点。

2.2 三层架构:语义、视觉、工程

我把 diagram-design 的骨架拆成三层,这个分层方式在多个项目里验证过,比较稳。

语义层回答“画什么”。它定义了一套图元词汇表:哪些概念需要用图形表示(服务、存储、队列、外部系统、用户),哪些概念需要用连线表示(同步调用、异步消息、数据流、控制流),哪些概念需要用容器表示(边界、分层、部署单元)。这一层的关键是封闭性——词汇表不能无限扩张,否则系统就退化成模板集合了。

视觉层回答“怎么画”。它把语义层的每个词汇映射到具体的视觉属性:形状、填充色、边框色、线型、箭头样式、字号、字重。这一层的关键是可区分性——任意两个语义不同的图元,在黑白打印、色盲模式、缩放到 50% 的情况下都必须能区分开。

工程层回答“怎么维护”。它把前两层固化成可执行的资产:设计令牌文件、绘图库、代码生成脚本、CI 检查规则。这一层的关键是可自动化——规范不能靠人肉记忆,要靠工具强制。

提示:三层里最容易跳过的是语义层。很多人直接进入视觉层,结果就是“配色很好看但图没有信息量”。我的建议是,语义层的词汇表不超过 12 个图元、6 种连线,超过这个数量就说明你在试图用一张图表达太多东西,应该拆图。

2.3 为什么选择“约束优先”而不是“自由优先”

设计系统领域有一个经典争论:应该给使用者更多自由,还是更多约束?diagram-design 明确选择后者。理由很实际:图的消费者(读图的人)数量远大于生产者(画图的人)。每增加一个视觉维度,生产者的表达力提升一点,但消费者的认知负担增加很多。约束优先的本质是把认知成本从消费者转移到生产者,而生产者只画一次,消费者要看很多次。

具体到操作上,约束优先意味着:

  • 颜色不是随便选的,而是从一组预设的语义色里挑;
  • 连线不是随便画的,而是从一组预设的关系类型里选;
  • 布局不是随便摆的,而是遵循一套网格和对齐规则。

这些约束听起来很烦,但实测下来,一旦团队适应了,画图速度反而会提升,因为“选择”这个动作被大幅简化了。

3. 核心细节解析:语义词汇表怎么定

3.1 图元词汇表的收敛过程

定语义词汇表最怕两件事:一是太少,表达不了复杂系统;二是太多,没人记得住。我的经验是从一个“最小可用集”开始,然后在真实项目里迭代。

最小可用集建议从这 8 个图元起步:

图元语义形状建议典型场景
服务可独立部署的计算单元圆角矩形微服务、函数
存储持久化数据的地方圆柱体数据库、对象存储
队列异步缓冲平行四边形消息队列、事件总线
外部系统不在你控制范围内的依赖虚线边框矩形第三方 API
用户人或其他系统的入口圆形终端用户、调用方
边界逻辑或物理分组虚线容器网络域、团队边界
同步调用请求-响应实线箭头RPC、HTTP
异步消息单向、可能延迟虚线箭头事件、通知

这 8 个图元能覆盖我见过的 80% 以上的架构图场景。剩下的 20% 怎么办?优先考虑用组合表达,而不是新增图元。比如“缓存”可以用“存储”加一个特殊标记来表示,而不是单独造一个图元。

3.2 颜色语义的分配原则

颜色是最容易滥用的视觉维度。diagram-design 对颜色的使用有三条硬规则:

规则一:颜色必须承载语义,不能只为了好看。如果两个图元颜色不同但语义相同,那就是噪音。如果两个图元语义不同但颜色相同,那就是歧义。

规则二:语义色不超过 6 种。人眼在快速扫视时能可靠区分的色相大约就是 5 到 7 种。超过这个数量,颜色就退化成装饰了。我通常这样分配:

  • 蓝色系:计算类(服务、函数)
  • 绿色系:数据类(存储、缓存)
  • 橙色系:消息类(队列、事件)
  • 灰色系:外部与边界
  • 红色系:仅用于错误路径或告警,正常图里不出现
  • 中性色:文字、辅助线

规则三:颜色必须通过灰度测试。把图转成灰度,如果两个语义不同的图元变得无法区分,说明它们的明度太接近了。解决方法是拉开明度差,而不是换色相。

注意:色盲友好不是可选项。大约 8% 的男性有某种程度的色觉障碍,其中红绿色盲最常见。如果你的图里红绿是主要区分手段,那对这部分读者就是不可读的。稳妥的做法是“颜色 + 形状 + 线型”三重编码,任意一重失效都不影响理解。

3.3 连线语义的细化

连线比图元更容易被忽视。很多人画图时所有连线都是同一种箭头,结果读图的人根本分不清哪条是同步调用、哪条是异步消息。diagram-design 建议把连线至少分成四类:

  • 同步调用:实线 + 实心箭头,表示调用方会阻塞等待;
  • 异步消息:虚线 + 实心箭头,表示发送方不等待;
  • 数据流:实线 + 空心箭头,表示数据方向而非控制方向;
  • 依赖:点线 + 无箭头或小箭头,表示编译期或逻辑依赖。

这四类在视觉上要能一眼区分。实测下来,线型(实线/虚线/点线)比颜色更可靠,因为线型在黑白打印和缩放下都稳定。

3.4 字号与间距的量化标准

视觉层里最容易被“凭感觉”处理的就是字号和间距。diagram-design 的做法是全部量化:

  • 图内主标题:16px,字重 600;
  • 图元标签:13px,字重 500;
  • 连线标签:11px,字重 400,斜体;
  • 注释文字:11px,字重 400,灰色;
  • 图元内边距:水平 12px,垂直 8px;
  • 图元间距:同一层级 24px,跨层级 48px;
  • 画布边距:四周 32px。

这些数字不是拍脑袋来的。13px 是大多数屏幕在 100% 缩放下正文可读的下限;24px 间距在 50% 缩放下仍然能看出分组;48px 跨层间距能形成明显的视觉节奏。你可以根据自己的输出场景调整,但关键是一旦定了就不要随意改,否则图与图之间就没有一致性了。

4. 实操过程:从零搭一套可落地的图设计系统

4.1 第一步:建立设计令牌文件

设计令牌(design tokens)是整套系统的单一事实来源。我习惯用一个 JSON 文件来管理,放在仓库根目录的design/下。

{ "color": { "compute": { "fill": "#E8F0FE", "stroke": "#1A73E8", "text": "#0B3D91" }, "storage": { "fill": "#E6F4EA", "stroke": "#137333", "text": "#0D5225" }, "queue": { "fill": "#FEF7E0", "stroke": "#B06000", "text": "#7A4200" }, "external":{ "fill": "#F1F3F4", "stroke": "#5F6368", "text": "#3C4043" }, "boundary":{ "fill": "none", "stroke": "#9AA0A6", "text": "#5F6368" } }, "font": { "title": { "size": 16, "weight": 600 }, "label": { "size": 13, "weight": 500 }, "edge": { "size": 11, "weight": 400, "style": "italic" } }, "spacing": { "nodePaddingX": 12, "nodePaddingY": 8, "siblingGap": 24, "layerGap": 48, "canvasMargin": 32 }, "stroke": { "sync": { "dash": "none", "width": 1.5 }, "async": { "dash": "6 4", "width": 1.5 }, "data": { "dash": "none", "width": 1.5 }, "depends": { "dash": "2 3", "width": 1 } } }

这个文件的好处是:任何工具都可以读它。draw.io 可以通过插件读,Figma 可以通过 Tokens Studio 读,代码生成脚本可以直接读。改一处,全局生效。

4.2 第二步:把令牌映射到绘图工具

不同工具的映射方式不一样,我分别说一下我实际用过的几种。

draw.io / diagrams.net:它支持自定义形状库(custom shape library)。你可以写一个 XML 文件,把每个图元的样式固化进去,然后作为自定义库加载。这样团队里每个人打开 draw.io 都能看到同一套图元。缺点是 XML 写起来比较繁琐,但一次写好可以长期用。

Figma:用 Tokens Studio 插件导入上面的 JSON,然后建一个组件库,每个图元做成一个 component,颜色和间距都绑定到 token。这样改 token 就能全局更新。Figma 的优势是协作和版本管理比较顺。

代码生成(Mermaid / Graphviz / PlantUML):如果你走“图即代码”的路线,可以写一个脚本,读 JSON 令牌,生成对应的主题文件。比如 Mermaid 支持%%{init: {'theme':'base', 'themeVariables': {...}}}%%,你可以用脚本把令牌注入进去。

提示:不要试图同时维护多套工具。选一个主力工具,其他工具只做导出。我见过团队里一半人用 draw.io、一半人用 Figma,结果就是两套规范逐渐漂移,半年后完全对不上。

4.3 第三步:写一份“图设计检查清单”

规范要落地,必须有检查手段。我通常写一份检查清单,放在 PR 模板里,画图的人提交前自己过一遍。

  • [ ] 所有图元是否来自预设词汇表?有没有自造图元?
  • [ ] 颜色是否只用了语义色?有没有为了“好看”加的颜色?
  • [ ] 连线类型是否明确?有没有“不知道算什么”的连线?
  • [ ] 灰度模式下是否仍可区分所有图元?
  • [ ] 字号是否统一?有没有手动调大的文字?
  • [ ] 对齐是否遵循网格?有没有肉眼可见的错位?
  • [ ] 图是否有标题和一句话说明?
  • [ ] 图内文字是否有拼写错误?

这份清单看起来简单,但实测能拦下 70% 以上的低级问题。剩下的 30% 需要人工评审,但至少评审时不用再纠结“这个颜色什么意思”了。

4.4 第四步:版本化与变更管理

图设计系统本身也需要版本管理。我的做法是给令牌文件加一个version字段,每次破坏性变更就升主版本号,并在 CHANGELOG 里写清楚“改了什么、为什么改、影响哪些图”。

破坏性变更的例子:把“服务”的填充色从浅蓝改成浅绿。这会导致所有旧图和新图不一致。处理方式是:要么批量重新导出旧图,要么在 CHANGELOG 里注明“旧图沿用 v1 规范,新图使用 v2”。

非破坏性变更的例子:新增一个“缓存”图元。这种变更不影响旧图,可以直接升次版本号。

注意:不要频繁改规范。我见过一个团队两个月改了四次配色,结果就是没人再认真遵守了。规范的权威性来自于稳定性。如果确实要改,攒一批一起改,不要零敲碎打。

5. 常见问题与排查技巧实录

5.1 图元太多记不住怎么办

这是最常见的问题。团队里总有人说“我记不住哪个颜色对应哪个语义”。解决方法不是逼人背,而是降低记忆负担:

  • 把词汇表做成一张“速查卡”,贴在绘图工具的模板里,打开就能看到;
  • 在绘图工具里把图元做成带标签的组件,鼠标悬停显示语义;
  • 把常用图元放在工具栏最前面,不常用的收起来。

实测下来,一个人连续画三张图之后基本就能记住核心的 5 到 6 个图元。剩下的靠速查卡就够了。

5.2 遇到词汇表覆盖不了的场景怎么办

比如你要画一个“定时任务”,词汇表里没有。这时候有三个选择:

  1. 用最接近的图元加标记。定时任务可以用“服务”加一个时钟图标。
  2. 用组合表达。定时任务可以画成“外部触发 + 服务”。
  3. 如果这个场景反复出现,考虑新增图元,但要走变更流程。

我的经验是,优先用前两种。新增图元的门槛要高,否则词汇表会膨胀。判断标准是:这个新图元在最近三个项目里出现过至少三次吗?如果是,才值得加。

5.3 灰度测试不通过怎么调

灰度测试不通过,说明两个图元的明度太接近。调整顺序是:

  1. 先调填充色的明度,拉开差距;
  2. 如果填充色调不动,调边框色的明度;
  3. 如果还不行,改形状或线型。

不要靠调色相来解决灰度问题,因为色相在灰度下本来就会丢失。形状和线型是更可靠的区分手段。

5.4 团队不配合怎么办

这是组织问题,不是技术问题。我的经验是:

  • 先做出样板。你自己用这套规范画三张图,在评审时展示“这样画读起来快多少”。
  • 找一两个愿意配合的同事,形成小范围共识。
  • 把检查清单放进 PR 模板,让规范变成流程的一部分,而不是额外的要求。
  • 不要一次推全套。先推颜色和字号,再推连线类型,最后推布局规则。

强制推行通常会反弹,渐进式渗透更有效。

5.5 常见问题速查表

问题现象可能原因排查方向解决建议
图看起来很乱对齐不一致检查网格和对齐开启对齐辅助线,统一间距
读图的人问“这个什么意思”语义不明确检查图元和连线是否有歧义补充图例,或改用更明确的图元
黑白打印后看不清明度太接近做灰度测试拉开明度差,增加形状区分
图与图之间风格不一致没有统一令牌检查是否都从令牌生成统一工具链,禁止手动调样式
改一处要改很多图没有用令牌检查是否硬编码样式迁移到令牌驱动的工作流
新人上手慢规范太复杂检查词汇表大小精简到 8 个核心图元,其余用组合

5.6 几个我踩过的坑

坑一:过早追求完美。我一开始花了大量时间调配色,结果发现团队根本不用,因为绘图工具里加载自定义库太麻烦。后来先把库做简单,能加载就行,再慢慢优化。

坑二:忽略导出场景。图最终要放到文档、PPT、网页里。不同场景对字号和对比度的要求不一样。我后来在令牌里加了一组“导出预设”,针对不同场景调整。

坑三:没有版本化。早期改规范没有记录,导致旧图和新图混在一起时完全不知道哪个是哪个版本。后来加了 CHANGELOG 才理清楚。

坑四:把规范当教条。有一次一个同事画了一个很特殊的图,用标准图元表达不了,我坚持让他用标准图元,结果图变得很难懂。后来我意识到,规范是服务于沟通的,不是反过来。特殊情况允许破例,但要在图里注明。

6. 工具选型与自动化扩展

6.1 主力工具怎么选

工具选型没有绝对答案,但有几个维度可以帮你决策:

维度draw.ioFigma代码生成(Mermaid 等)
上手难度低中高
协作能力中高低(靠 Git)
版本管理弱中强
自定义能力中高高
适合场景快速画图设计协作图即代码

我的建议是:如果团队以工程师为主,走代码生成路线;如果以设计和产品为主,走 Figma;如果是混合团队,draw.io 是折中选择。

6.2 用脚本做一致性检查

如果你走代码生成路线,可以写一个简单的检查脚本,在 CI 里跑。比如检查所有图源文件里有没有硬编码的颜色值:

import re import sys from pathlib import Path TOKEN_COLORS = {"#E8F0FE", "#1A73E8", "#E6F4EA", "#137333", "#FEF7E0", "#B06000", "#F1F3F4", "#5F6368"} def check_file(path): text = Path(path).read_text(encoding="utf-8") colors = set(re.findall(r"#[0-9A-Fa-f]{6}", text)) illegal = colors - TOKEN_COLORS if illegal: print(f"{path}: 发现非令牌颜色 {illegal}") return False return True if __name__ == "__main__": ok = all(check_file(p) for p in sys.argv[1:]) sys.exit(0 if ok else 1)

这个脚本很粗糙,但能拦住大部分“随手调色”的情况。跑在 CI 里,PR 不通过就不让合并。

6.3 自动生成图例

图例是图设计系统里最容易被忽略的部分。每张图都应该有图例,但手动维护图例很烦。我的做法是写一个脚本,从令牌文件自动生成图例的 SVG 或 PNG,然后插入到图里。

import json def render_legend(tokens, output="legend.svg"): items = [] y = 0 for name, style in tokens["color"].items(): items.append( f'<rect x="0" y="{y}" width="24" height="16" ' f'fill="{style["fill"]}" stroke="{style["stroke"]}"/>' f'<text x="32" y="{y+13}" font-size="12">{name}</text>' ) y += 24 svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="200" height="{y}">' \ + "".join(items) + "</svg>" open(output, "w").write(svg) if __name__ == "__main__": tokens = json.load(open("design/tokens.json")) render_legend(tokens)

这样图例永远和令牌一致,不会出现“图例里有的颜色图里没有”这种尴尬。

6.4 和文档系统集成

图最终要放到文档里。如果你的文档用 Markdown,可以把图源文件和文档放在同一个仓库,用 CI 自动导出 PNG 并插入。这样改图源就自动更新文档,不用手动替换图片。

具体做法是在 CI 里加一步:

# 假设用 draw.io 的 CLI 导出 drawio --export --format png --output docs/images/ diagram/*.drawio

然后文档里引用docs/images/xxx.png。每次合并 PR,图片自动更新。

7. 从单图到体系:这套方法还能怎么扩展

7.1 扩展到其他图类型

diagram-design 最初是为架构图设计的,但这套三层框架可以扩展到其他图类型:

  • 时序图:语义层定义参与者、消息、激活块;视觉层定义生命线样式、消息箭头;工程层用 PlantUML 或 Mermaid 生成。
  • 状态机图:语义层定义状态、转移、守卫条件;视觉层定义圆角矩形、箭头、标签位置。
  • 流程图:语义层定义开始/结束、处理、判断、输入输出;视觉层定义标准形状和连线。

每扩展一种图类型,就新增一份令牌文件和一份词汇表,但三层框架不变。

7.2 扩展到非技术场景

这套方法不限于技术图。我见过有人用它来规范:

  • 业务流程图:统一泳道、角色、活动、网关的视觉表达;
  • 组织架构图:统一层级、汇报线、虚线的表达;
  • 用户旅程图:统一阶段、触点、情绪曲线的表达。

核心逻辑是一样的:先定语义,再定视觉,最后工程化。

7.3 和 AI 辅助绘图的结合

现在有一些工具可以根据文字描述生成图。但生成出来的图往往不符合你的设计系统。一个可行的做法是:把令牌文件和词汇表作为提示词的一部分,让生成工具按你的规范输出。比如在提示词里写“使用以下颜色语义:计算类用 #E8F0FE 填充、#1A73E8 边框……”。这样生成出来的图至少颜色是对的,剩下的布局再手动调。

7.4 我个人在实际操作中的体会

这套东西我断断续续做了两年多,最大的体会是:图设计系统的价值不在于图变好看了,而在于沟通成本降下来了。以前评审一张架构图,前十分钟都在问“这个框什么意思”“这条线什么意思”;现在这些基础问题基本消失了,评审直接进入“这个设计合不合理”的层面。

另一个体会是:不要追求一步到位。我一开始想设计一套覆盖所有场景的完美系统,结果做了三个月还没落地。后来改成“先解决最痛的三个问题”——颜色混乱、连线歧义、字号不一——两周就上线了,然后在用的过程中慢慢补。

最后一个建议:把规范写进工具里,而不是写进文档里。文档没人看,工具天天用。你能让工具自动做的事,就不要指望人自觉去做。这是我从多次推行失败里学到的最实在的一条。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询