1. 为什么做 diagram-design:从一张丑图说起
1.1 一张混乱的图,毁掉一次评审
我最早被 diagram-design 这个概念击中,是在一次方案评审会上。当时某位同学花了一周时间画架构图,投影一打开,所有人都沉默了:线条随意交叉,节点大小忽大忽小,黄色和绿色混在一起看不清边界,箭头方向有的朝右、有的朝下,根本分不清是调用关系还是数据流向。评审用了二十分钟,大部分时间都花在“你这张图到底想表达什么”上,方案本身反而不是重点。
这不是个例。很多人以为画图就是“把方框和箭头拖出来”,拖完就结束。但实际上,一张没有设计过的图表,和一份没有排版的文档一样,信息量再大,也很难被人接受。架构图、流程图、思维导图、时序图,本质都是把抽象关系变成视觉关系,如果视觉关系本身是混乱的,读者就会把“看不懂图”误判成“理解不了业务”。diagram-design 这个项目,就是为了解决这个问题。
我给它下的定义很短:diagram-design 是一套关于图表的视觉表达规范,覆盖布局、连接线、颜色、文本、图标和导出流程。它不是一个绘图软件,也不是一个模板库,而是把“画清楚图”这件事从个人手感,变成团队可以共同遵守的规则。
这套东西适合谁?如果你需要画技术架构图、业务流程泳道图、系统时序图,或者你在团队里负责统一文档风格,都会从中受益。即使你从来不画图,只是经常看别人画的图,也能用这套标准去判断一张图到底哪里别扭、怎么改。项目做了几轮迭代后,我自己最大的感受是:图表设计不是“美化”,而是把思考过程显性化。先有清晰,再有风格。
1.2 diagram-design 的定位与目标
项目立项的时候,我给 diagram-design 定过三个目标,直到现在都在用。
第一目标是可复用。团队里每张图都从空白画布开始,是最差的状态。diagram-design 会沉淀出一批基础元件、颜色变量、布局模板,让任何一个人拿到后,都能在半小时内画出一张规范图,而不是从零开始摸索。
第二目标是可解释。对每一处设计规则,都要能回答“为什么”。比如为什么连接线用正交线而不用曲线,为什么节点间距是 16 而不是 13,为什么强调色只给一种。这些看起来很琐碎,但恰恰是规则能持续被执行的根基。规则一旦没有理由,就会被人以“我觉得这样更好看”为理由破坏。
第三目标是可沉淀。图表要能像代码一样被维护,而不是画完就再也动不了。为此 diagram-design 特别强调分层、分组、命名和源文件管理。图上每一个元素,都应该有明确的语义身份:它是容器、节点、标签,还是注释。这种结构化思维,决定了图表后期的可维护性。
从项目形态上说,diagram-design 会拆成几个模块:画布规范、元素规范、布局规范、色彩与文本规范、导出与协作规范。后文我会逐个讲清楚。
2. 图表设计的第一层:清晰优先,好看次要
2.1 决定阅读顺序:方向、主线、分组
图表设计里最容易被忽略、也最影响阅读体验的,是阅读顺序。
人眼阅读图表有一定的天然倾向:横向优先于纵向,左上优先于右下。所以大多数架构图、系统图,我默认采用“从左到右”的主方向,让主流程横着走;只有时间先后关系特别强的图,才考虑“从上到下”。方向一旦统一,读者不需要来回转头,认知负担立刻降下来。
方向定完后,要分清主线和支线。一张图里只能有一条视觉主线,其他都是支线。主线上的节点,用更粗的边框、更实的填充、更大的字号;支线节点则降级处理。很多图之所以显得乱,就是所有节点长得一样,所有连线一样粗,读者根本分不清哪些是核心路径,哪些是异常分支。diagram-design 的做法是在设计稿阶段就先标出“主路径”,再让主路径在视觉上压过其他元素。
分组也很重要。节点超过七八个,就应该分组。分组的常见方式有四种:用泳道(横向区域)表示不同子系统;用容器(大圆角矩形)表示不同模块;用背景色块表示不同层级;用留白拉开不同区块。四者可以混用,但一组图里最多用两种,否则视觉噪音会盖过信息本身。
阅读顺序最终要落在网格和间距上。diagram-design 强制使用 8 的倍数作为间距基准:节点与节点之间 16,容器内边距 24,模块之间 48。这样排出来的图天然有节奏感,缩小后看也不会糊成一团。
2.2 节点与连接线的“隐含规则”
很多人画图不好看,问题不在审美,而在没有给节点和连接线建立规则。
先看节点。一个基础节点,通常包含三部分:外层轮廓、内部标题、可选图标。轮廓我建议优先用圆角矩形,圆角不要超过 8 像素。圆角太大显得卡通,太小显得生硬。边框粗细上,普通节点 2,主节点 4,辅助节点可以用 1。同一张图里,边框粗细的档位最多三档,多了就失去意义。
节点尺寸上,我踩过很深的坑是“文字决定节点”。同一个层级的节点,文字量不同,画出来就一个宽一个窄,参差不齐。diagram-design 的解法是给节点设定最小宽高,文字用统一的宽度约束,超出就换行而不是拉伸节点。同级节点的视觉重量保持基本一致,整体才稳。
再看连接线。连接线有五种常见形态:正交线、直线、曲线、弧线、折线。我的经验是,技术类图表优先用正交线,也就是“先横再竖、只走直角”的连线。正交线看着笨,但对齐感最强,特别适合表达具有层级关系的调用链;而曲线适合表达柔性流程,比如用户行为路径、产品状态流转,曲线有一种流畅感,但不适合密集场景。
箭头是连接线语义的核心。diagram-design 里规定:箭头的核心语义是“方向”,不能有歧义。所以箭头的尺寸要在缩略图状态下依然可见,末端不能贴着节点边框,最好留出 4 到 8 像素的间隙。两条线相交时,要避免直接在另一个节点上方穿越;如果必须穿越,优先绕行而不是硬穿。
2.3 一套有限的颜色与文字系统
图表里的颜色,比普通界面设计更考验克制力。
我见过大量技术图把红、黄、蓝、绿、紫全部用上,结果读者首先记住的不是关系和逻辑,而是一堆颜色块。diagram-design 的色彩规范只有四类:基础色、层级色、语义色、强调色。
基础色负责大面积的节点和容器,通常用低饱和度的灰、白、深灰,保证背景干净。层级色用来区分两个相邻层级,常见做法是同一色相下控制深浅,而不是换一个完全不同的色相。语义色只表达特定含义,比如红色表示报错或拒绝,绿色表示成功或通过,黄色表示警告,数量上不超过三四个。强调色全图最多出现一种,只用在最重要的主路径或核心节点上。强调色一多,等于没有强调。
颜色之外,文本的规则常常被人忽略。diagram-design 规定:图表内标题字号不小于 14,正文不小于 12;一个节点内部最多两级文字层级;全图最多使用两种字体,中文建议使用同一款开源字体或系统黑体,英文和数字使用无衬线字体。字号不需要到处都大,小的更大、大的更要克制。
图例和标注也要纳入规范。只要图中出现超过一种语义色,就必须带图例。图例放在图的右下角或左下角,内容顺序和图内使用顺序一致。标注线统一用浅灰色细线加斜体文字,避免和正式连接线混淆。
3. 实操落地:diagram-design 的完整搭建过程
3.1 工具选择的三个分岔路
diagram-design 的实操第一步,不是画图,而是选工具。工具选错,后面所有规范都会被带偏。
市面上的绘图工具大致分三类。第一类是拖拽式白板产品,上手快,适合做头脑风暴和方案讨论,节点、连线都可以直接用鼠标操作;缺点是排版能力弱,图一旦复杂,对齐和图层管理会很痛苦。第二类是专业矢量设计工具,像素级控制、图层体系完整,适合做对外交付的高质量示意图;缺点是学习成本高,不适合实时协作。第三类是文本化图表工具,用类似代码的方式描述图形,再由工具渲染成图,天然适合版本管理,和代码仓库能放到一起;缺点是布局调整不直观,刚开始学习曲线比较陡。
我最终选择的组合是:快速讨论用拖拽白板,正式沉淀用矢量工具,需要进代码仓的图用文本化工具。这里并不推荐某一款具体产品,因为更新太快,但原则是固定的:至少有一个工具支持 SVG 导出;至少有一个工具支持图层和分组;至少有一个工具能离线使用。
确定工具的同时,要确定画布参数。diagram-design 默认画布比例为 16:9,基础画布宽度 1920,高度 1080。原因很简单:这个比例在现代屏幕和投影上都不会出现大面积留白或裁切。网格尺寸设成 16,吸附开成“对齐网格”而不是“对齐像素”,保证后续所有间距都能落到 8 的倍数上。
3.2 定义基础画布、网格与组件库
工具选完后,就到了 diagram-design 项目里最核心的部分:搭建基础组件库。
我把组件库拆成五类,每一类都有明确的命名规则:
| 组件类型 | 用途 | 命名示例 |
|---|---|---|
| 容器 | 表达系统、模块、泳道 | container-system-a |
| 节点 | 表达实体、操作、页面 | node-service-b |
| 连接线 | 表达关系、流程、状态 | edge-call-c |
| 标注 | 表达说明、注释、数据来源 | label-detail-a |
| 图例 | 表达颜色和符号含义 | legend-status-a |
命名的意义在于,导出 SVG 后依然能通过名字快速定位元素。如果后期要做画布自动分析,这个命名习惯能让脚本轻松统计节点数量、连接线密度和未对齐元素。
组件库里最重要的,是一套标准 yaml 样式配置。我贴一份简化过的示例,你在自己的项目里可以直接改:
canvas: width: 1920 height: 1080 grid: 16 background: "#f8fafc" text: title: fontSize: 20 fontWeight: 600 lineHeight: 28 color: "#1e293b" body: fontSize: 14 lineHeight: 20 color: "#475569" node: default: width: 160 height: 48 fill: "#ffffff" borderColor: "#94a3b8" borderWidth: 2 radius: 8 primary: borderColor: "#0f766e" borderWidth: 4 fill: "#f0fdfa" edge: default: type: orthogonal strokeWidth: 2 color: "#94a3b8" arrowSize: 6 mainPath: strokeWidth: 4 color: "#0f766e" spacing: gapBetweenNodes: 16 containerPadding: 24 groupPadding: 48这套配置有两个关键点:第一,所有颜色都用十六进制色值,不用“浅蓝”“深灰”这种模糊词,方便跨工具复用;第二,所有间距都落到 8 的倍数。组件库的元件不直接存储颜色值,而是引用配置里的变量名。后续品牌色变化时,只改配置,所有图同步更新。
3.3 模板与导出流程
组件库建好之后,不要急着画每一张图,而是先做模板。diagram-design 的模板库按图型分类:架构图模板、流程图模板、泳道图模板、时序图模板、状态图模板。每个模板只固定布局框架和视觉元素,不固定具体内容。
架构图模板的布局逻辑是:上层放入口,中间放核心服务,下层放基础设施,左右两边放外部依赖。流程图模板则默认从上到下,分支用正交线,判断节点用菱形。泳道图模板横向分泳道,每个泳道代表一个角色,事件从左向右流动。
导出流程同样要规范。diagram-design 的导出标准有三条:任何对外交付的图,优先导出 SVG;需要嵌入文档或演示时,再导出高分辨率 PNG;禁止直接从画布截图。SVG 的好处不用多说,无限缩放、体积小、还能被搜索引擎解析;PNG 导出时,缩放倍率建议不低于 2 倍,也就是分辨率至少是 1920 宽。
导出的命名也要统一,格式是:项目名-图型-描述-版本号.svg。比如billing-system-arch-core-services-v2.svg。文件名能体现内容,才不会出现一堆“未命名文件”。模板和源文件一定要归入版本管理,不能只存在个人电脑里。
4. 踩过的坑与排查技巧实录
4.1 节点一多就失控:拥挤和粘连
diagram-design 做了几轮之后,我遇到最多的问题是:节点少的时候一切正常,节点超过二十个,图就开始失控。
最常见的原因是间距没有守住。人的视觉习惯会把相近的元素自动看成一类,当两组毫无关系的节点相距只有 12 像素时,读者会默认它们是一伙的。调整方案不是把图拉大,而是把分组间距刻意拉开到 48,让读者在一米之外也能分辨出区块边界。
第二个原因是节点没有最小尺寸约束。某些模块只有一个词,比如“缓存”,某些模块却要放下三四行注释,如果不设最小宽高,整张图就像用不同尺寸的纸片拼出来的。解法是给每一类节点固定基础宽高,文字一多就压缩行文,而不是撑大节点。
第三个原因,也是最隐蔽的:次要元素刷存在感。图例、标注、注释这些辅助内容,字体太大、边框太明显,视觉重量甚至超过了主节点。我的排查习惯是画完图后眯着眼看一遍,眯眼后最先看到的应该是主流程,如果最先看到的是图例或某个标注,说明辅助元素必须降级。
4.2 箭头方向和时间轴顺序混乱
流程类图表里,箭头方向混乱是最容易引起争吵的问题。
有人画接口调用图,习惯把请求方向画成从左到右,返回方向画成从右到左,结果两条线上下重叠,读图的人分不清谁先谁后。diagram-design 的规则是:一个连接线上只能承载一种主语义。如果要同时表达请求和返回,使用两条独立线,并在线上标注“请求”“返回”;如果担心线太多,用虚实线区分两类语义,而不是靠方向划分。
时间轴混乱则更隐蔽。有些绘图工具允许节点自由摆放,画的时候觉得哪里空就补一个节点进去,最后从上到下看,时间顺序却是乱的。我建议时间类图表一定用泳道加编号:每个大阶段用竖向泳道隔开,节点左上角加序号,序号就是阅读顺序;读者即使不看箭头,也能靠序号知道流程。
4.3 颜色多得像圣诞树、字体大小忽大忽小
还有一个几乎每个团队都会踩的坑,是用颜色来表达“重要程度”。
如果这张图七个节点都重要,你会用七种颜色分别标出来。结果就是没有重点。diagram-design 的做法是,重要程度只在两个维度上区分:一是边框粗细,二是强调色的有无。普通节点灰色细框,重要节点深色粗框,最关键的主路径铺一层强调色。其余所有信息,都不允许再增加第三种颜色。
字体大小也是重灾区。同一个图层里,有人为了填满空间把字体拉大,有人为了塞进内容把字体缩小。最终导出图片后,放大的标题和缩小的正文混在一起,非常刺眼。排查方法很简单:全图标题只允许出现一种字号,同级节点内部文字只允许出现一种字号;如果节点文字太长,缩短措辞,而不是缩小字号。
4.4 常见问题速查表
| 现象 | 可能原因 | 排查与解决 |
|---|---|---|
| 节点之间挤作一团 | 间距没有落到规范值,分组不足 | 把同级间距统一为 16,分组间距拉到 48 |
| 线条交叉横七竖八 | 连接线类型不统一,路由不清晰 | 统一用正交线,主路径绕开密集区 |
| 箭头方向看不懂 | 连接线承载两种及以上语义 | 拆成两条线,或用虚实线区分语义 |
| 不同节点大小不一致 | 没设最小宽高,文字撑开节点 | 固定节点基础宽高,文字一律换行 |
| 颜色一多就没重点 | 用颜色表达重要程度 | 重要程度改由边框粗细和强调色表达 |
| 导出后文字发虚 | 直接截图或导出分辨率不足 | 优先导出 SVG,PNG 要 2 倍以上缩放 |
| 改需求要重新画一张 | 组件库和模板未沉淀 | 从模板复制,改配置而不是重画 |
| 团队各画各的风格 | 没有统一规范和命名 | 用 yaml 配置统一色值、间距、字号 |
这张表我贴在了团队文档首页。每次有人来问“这张图哪里不对”,我先不回答,让他对照表格自查一遍。结果是百分之七八十的问题,都出在这个表格里。
5. diagram-design 在真实项目里的更多用法
5.1 架构图之外:状态图、时序图如何共用同一套风格
diagram-design 不只适用于架构图。我在实际项目里,把同一套颜色系统和间距标准应用到了状态图和时序图上,效果同样稳定。
状态图的核心是状态与流转。状态节点用圆角矩形,开始和结束用胶囊形,流转线上写触发事件。颜色上,普通状态用基础灰,当前状态用强调色,不可达或废弃状态用浅灰加虚线。这套规则和架构图兼容,读者看到实线就知道是正常流转,看到虚线就知道是异常分支。
时序图则更强调对齐。生命线垂直向下,消息线水平向右,两者交叉处最容易乱。我的处理方式是:生命线统一用 2 像素深灰,激活条用 4 像素强调色,消息线用正交线。这样即使线条很多,读者依然能沿着颜色和粗细找到主线。时序图的文字很小,所以字号规范格外重要:消息描述最小 12,超过 20 个字符就换行,禁止倾斜文字表达动作。
共用一套风格最大的好处是跨图认知成本低。读者在架构图里看懂“绿色代表成功路径”后,在状态图里看到同一种绿,不需要重新学习。这种一致性,恰恰是 diagram-design 最核心的价值。
5.2 让图表自动出现在文档里
项目用了一个季度的组件库之后,我开始考虑更新维护的问题。静态图最大的痛点是,系统架构一变,所有人手上的截图都是旧的。
为此我把一部分图表改成了文本化的表达方式,让图表和代码描述放在一个目录下,由构建流程自动渲染成图片,再嵌入文档。基本流程是:维护一份文本描述文件,里面用简单语法声明节点、连接、分支;提交代码时启动渲染脚本,输出 SVG,同时更新文档引用。这样架构调整后,只需要修改文本描述,重新提交,整篇文档里的图就同步更新了。
这条流程不是没有成本:文本化描述在复杂排版上不如拖拽工具灵活,但胜在“可跟踪、可审查、可回溯”。某一次评审中,大家发现一张接口关系图和上一版本只有一处细微差别,直接从提到“改了哪一行”定位到具体变更,而不是靠肉眼对比两张图片。对技术团队来说,这种可维护性比排版自由重要得多。
最后再分享一条我自己的习惯:无论图有多复杂,画完之后一定删掉那些“装饰性”元素——多余的阴影、渐变色、模拟 3D 效果、花哨的背景纹理。图表设计做久了,你会越来越体会到,好的图不是让人看一眼就惊艳,而是让人扫一眼就懂。diagram-design 真正想做的,就是把这种“扫一眼就懂”从偶然变成必然。