做了几年架构和技术管理,我画过的图应该不少于几百张。但真正让我下决心做 diagram-design 这个"图表设计"项目,是因为一次很尴尬的评审:同一套系统,三个人画了三张结构完全不同的架构图,连"谁调用谁"这种最基本的关系都对不齐。后来我发现问题不在画图的人,而在没有任何规则约束"图到底应该怎么画"。
diagram-design 并不是某个炫酷的绘图工具,而是一整套关于图表设计的规范、组件资产和落地方案。它解决的是那种特别普遍但又一直被忽视的问题:团队里的架构图、流程图、时序图、数据流图,为什么总是看起来像不同人画的?连线交叉、颜色泛滥、字号混乱、箭头含义各说各话——这些问题靠临时口头沟通根本治不住,必须靠一套统一的图表设计系统来兜底。
这套方案适合三类人:一是经常需要画架构图、流程图的技术人员,想让自己交付的图更专业、更规范;二是团队负责人,想建立统一的图表设计标准,减少沟通成本;三是做数据可视化、前端组件库的人,需要一套可复用的图元体系和主题配置。不管你是刚入行的新人还是写过不少图的老手,这篇文章里讲的东西都能直接用上。
1. 为什么做 diagram-design:从"随手画"到"规范画"
1.1 没有规范时,图表设计到底乱在哪
我先说说没有规范的时候,团队画图最常见的四个乱象。
第一个乱象是图元语义混乱。同样一个矩形框,A同学用来表示"服务",B同学用来表示"数据库",C同学拿来表示"外部系统"。看单张图没问题,一旦把多张图放在一起对照,读者就得反复确认"这个框到底是什么"。图表原本是为了降低理解成本,结果语义不统一反而成了理解障碍。
第二个乱象是连线含义全凭感觉。实线是调用、虚线是异步、箭头表示流向,这些约定很多人在用,但没人明确定下来。结果就是有的图里虚线表示"将来可能有的关系",有的图里实线反而表示"数据返回",同一张图里既有正交折线又有自由曲线,交叉点密密麻麻。读图的人不得不靠上下文和猜测去理解连线意图。
第三个乱象是颜色完全失控。画图时几乎每个人都会给"自己的模块"选一个独一无二的颜色,最后一张图能有十几种颜色,而且深浅不一、饱和度各异。颜色一旦批量涌入,主次关系就彻底消失了,读者根本分不清哪个是核心链路、哪个是边缘模块。
第四个乱象是字号、间距、对齐都没有约束。有的节点字很大、有的字很小,节点之间有的紧贴、有的空出半屏,居中靠左全靠鼠标手感。这种细节单独看都不致命,但累积起来就是强烈的"杂乱感"。
这四个乱象叠加在一起,就是那次评审会上三张架构图互相说不清的根本原因。所以 diagram-design 的第一目标不是把某一张图画漂亮,而是把"画图的口径"统一起来。
1.2 diagram-design 要解决的三个核心问题
我梳理了 diagram-design 需要重点解决的三个问题,后面所有的规范、模板、代码都是围绕这三个问题来设计的。
第一个是产出一致性。不管你用的是什么画图软件,任何人引用同一套图元、同一份配色、同一种连线规则,产出的图都应当在直观感受上"来自同一个体系"。一致性比单张图的美观程度重要得多,因为它意味着整个团队共享同一套视觉语言,评审时大家的注意力会放在逻辑关系上,而不是花在互相解释图例上。
第二个是复用效率。大多数团队画图,90%的图元其实都是重复的——服务节点、数据库节点、网关、用户角色、消息队列,这些元素每张图都会出现。如果每次画图都从零开始拖矩形、调颜色、补文字,效率一定低得吓人。diagram-design 要做的是把这些高频图元沉淀为模板和组件,拖进来即用,统一的样式已经预置好了。
第三个是可持续演进。图表设计规范不能是一份写完就吃灰的文档,它必须跟随业务、跟随工具、跟随团队认知一起迭代。图元要能增补、配色要能换主题、导出格式要能对接文档平台。这也是为什么我在落地时坚持把所有规范参数用配置文件管理,后面你会看到具体的做法。
1.3 这套方案适合谁,能带来什么实际收益
说句实在话,如果只是个人画一张临时草图,规范不规范的其实无所谓。但只要你需要在团队内协作、需要把图交付给上下游、需要跨时间维护一批图表,那整套方案的价值就体现出来了。
对个人来说,最大的收益是画图速度变快、成图质量变高。有了预置的节点模板、连线样式和布局规则,一张架构图从构思到成稿的时间能压缩一半。而且因为所有细节都是定好的,你不太需要反复调整样式,可以把精力花在梳理逻辑关系上。
对团队来说,最大的收益是评审效率变高、沟通摩擦变少。一次架构评审里,所有人默认"圆角矩形是功能模块、圆柱是存储、实线是同步调用、虚线是异步消息",讨论可以直接进入逻辑层面。谁对谁错一目了然,不再需要"你说明一下这个箭头是什么意思"这种低质量对话。
对做工具或组件库的开发者来说,这套方案提供了一套可落地的设计语义和参数体系。你可以参考它去设计自己的图元组件、主题系统和布局算法,而不是再从一张空白的画布开始摸索。
2. 核心设计规范:先把"画图底层"定下来
2.1 画布、网格与比例:为什么是 8 和 16 的倍数
diagram-design 的第一个设计决策,是定画布尺寸、网格步长和节点边距。
我在项目里默认采用16px 网格、8px 步进的规则。意思是画布上所有节点的坐标、大小、间距,都尽量落在 8px 的整数倍上;对齐辅助线和吸附网格则按 16px 生效。之所以选这两个数字,不是因为拍脑袋,而是因为它们与绝大多数设计体系的基础栅格保持一致。主流设计工具的像素对齐、浏览器的 CSS 像素、常见的显示分辨率缩放比例,都是基于 8 或者 16 的倍数,这样在导出高清图、嵌入网页、对接前端组件时,可以避免半像素导致的模糊和错位。
默认画布尺寸我设了两个档位:横版 1920×1080,竖版 1280×1600。1920×1080 适合表达"一个业务系统的整体架构"这种横向结构;1280×1600 适合表达"一条完整流程从开始到结束"这种纵向结构。项目里通过画布模板来切换,不需要每次手动拖拽调整。
节点内部的 padding 也有固定标准。我用的是:节点左右内边距 16px、上下内边距 12px、文本与图标之间的间距 8px。这样设定的原因,是要保证一个节点里无论是纯文字、还是图标加文字,视觉重心都比较稳,不会出现文字顶到边框或者图标跟文字挤在一起的观感。
用网格体系还有个隐藏的好处:自动布局算法实现起来更简单。比如节点之间的水平间距直接取 24px、垂直间距直接取 32px 的整数倍,算法里就不需要再做复杂的碰撞检测,排出来的图天生整齐。
2.2 节点体系:形状、颜色、文本都要有语义
diagram-design 把节点当成语义单元来设计,而不是当成随意画的几何图形。每类节点都有相对固定的形状、颜色和文本规则。
形状表意是整个体系的地基。我这里给出一套常用映射,直接抄走就能用:
| 形状 | 语义 | 典型用途 |
|---|---|---|
| 直角矩形 | 系统、服务、应用 | 业务系统、微服务、第三方平台 |
| 圆角矩形 | 功能模块、处理步骤 | 订单处理、鉴权模块、定时任务 |
| 菱形 | 判断、分支 | 条件判断、路由规则 |
| 圆柱形 | 存储、数据库 | MySQL、缓存、对象存储 |
| 椭圆 | 角色、外部实体 | 用户、商户、外部系统 |
| 六边形 | 网关、调度器 | API 网关、消息网关、任务调度 |
形状的语义一旦定下来,就不要轻易突破。比如你在架构图里看到一个圆柱形,就应当默认是存储,而不是"这张图里圆柱表示消息队列"。这不是限制创造力,而是保证多人协作时信息不衰减。
颜色体系我采用"功能色 + 状态色"双轨制。功能色用于表达节点类型之间的层次差异,比如主链路用蓝色系、辅助模块用灰色系、外部系统用绿色系;状态色用于表达运行状态,比如正常、异常、降级、未知,用绿色、红色、橙色、灰色来表示。关键是控制颜色数量:一张图里功能色最多 4 种,状态色只出现在需要表达运行态的节点上,不允许每加一个模块就新增一个颜色。
文本层级分三档。节点标题用 16px、字重 600;节点内的辅助说明用 12px、字重 400;注释和标注文字用 11px、字重 400、颜色降一档透明度。三层字号拉出了信息层级,读者一眼就能区分"这是标题""这是解释""这是备注"。文本默认左对齐,长文本第二行缩进 8px 对齐,这是一个很小但很影响细节的规则。
2.3 连线与流程:实线、虚线、箭头与拐角规则
如果说节点是图表的骨架,连线就是图表的血管。血管不通,整张图就废了。diagram-design 对连线的设计花了不少心思,主要围绕四个方面。
线型与语义绑定是第一条规则。实线表示同步调用、数据推送、强依赖;虚线表示异步通知、事件消息、弱依赖;点线表示"计划中""未来可能"的关系。箭头的方向必须严格按照"数据或控制流向"来画,不允许出现"双向箭头表示两个服务相互调用"这种偷懒做法。如果确实需要表达双向调用,就画两条方向相反的实线,并在线上标注各自的语义。
线宽与主次关系绑定。核心链路(比如用户请求的主路径)用 2.5px;次要链路用 1.5px;辅助标注线用 0.5px。线宽的差异虽然细微,但在复杂的架构图上能非常有效地引导视线:读者先顺着 2.5px 的粗线看完整条主线,再回头看支线,理解顺序就清晰了。
拐角规则我强烈建议用正交折线。架构图、流程图这类技术图示,正交折线(即水平垂直的直角折线)比自由曲线更专业。原因是人眼对水平方向和垂直方向的路径追踪速度远高于斜线,直角拐弯能最大程度减少视觉干扰。只有在表达"非确定性的流转"时,才使用曲线,而且曲线要控制在两张节点之间的半透明弧线,不穿过其他节点。
连线的间距与避让也有标准:连线之间至少保持 24px 间距,连线与节点边框至少保持 16px 间距;连线穿过节点时,必须从节点间"预留通道"走,而不是盖在节点上面。每次布线完毕,要检查是否存在两条连线交叉且无法避免的情况,如果出现,就调整其中一个节点的位置来解交叉,而不是随意改连线路径。
3. 落地实操:把规范变成能直接用的设计资产
3.1 第一步:定义一份可复用的主题配置
规范写出来是给团队看的,但如果只停留在文档层面,执行起来一定会走样。所以我在 diagram-design 里做的第一件落地工作,是把所有规范参数变成一个配置文件,谁画图谁引用这份配置。
这个配置文件用 JSON 来承载,结构大致是这样:
{ "canvas": { "width": 1920, "height": 1080, "gridSize": 16, "snapStep": 8 }, "theme": { "primaryColor": "#2563EB", "secondaryColor": "#64748B", "externalColor": "#059669", "dangerColor": "#DC2626", "warningColor": "#D97706", "textColor": "#0F172A", "labelColor": "rgba(15, 23, 42, 0.6)", "lineColor": "rgba(15, 23, 42, 0.75)", "coreLineWidth": 2.5, "normalLineWidth": 1.5, "auxLineWidth": 0.5 }, "typography": { "titleFontSize": 16, "bodyFontSize": 12, "noteFontSize": 11, "titleFontWeight": 600 }, "node": { "service": { "shape": "rect", "width": 180, "height": 56, "cornerRadius": 0 }, "module": { "shape": "rect", "width": 180, "height": 56, "cornerRadius": 8 } } }这份配置的好处是,它把散落在每个人脑子里的"我觉得应该这样画"统一成了一份机器可读的标准。无论是后续开发自定义拖拽面板、做自动布局,还是对接文档生成工具,都可以直接读取这个 JSON。团队里任何一张图引用的都是同一份主题,自然就长一个样。
一点经验之谈:这份配置一定要用版本管理工具管理起来,任何人要修改配色、字号、图元尺寸,都必须走提交记录。否则改来改去,又会出现"上周的图跟这周的图风格不一样"的新问题。
3.2 第二步:沉淀高复用度的图元模板库
有了配置规范,下一步就是把高频出现的节点做成模板。我建了四个基础模板组:基础架构组(服务、数据库、网关、消息队列、缓存)、业务功能组(订单、用户、支付、库存等抽象业务模块)、角色实体组(用户、商户、管理员、外部系统)、连接线类型(同步调用线、异步消息线、依赖线、未来关系线)。
每个模板不是一个"死形状",而是带默认行为参数的活组件。比如数据库模板,拖入画布后自动带上圆柱形状、存储功能色、标题文本占位符,你只需要改名称就行。网关模板拖入后默认是六边形,并且预置了一条指向下游服务的连线端口,这样当你从网关向外拉线时会自动吸附到端口上,不会出现连线从文本框中间穿过的尴尬。
模板库还要配套一个"图例页"。我建议团队在每张比较复杂的图右下角放入一个小图例,说明"实线=同步调用、虚线=异步消息、圆柱=存储"这些基本语义。图例不是给画图的人看的,是给第一次接触这张图的读者看的,它能大幅降低读图门槛。
3.3 第三步:布局与自动排版怎么做
画图时最花时间的环节往往不是逻辑梳理,而是排版:节点放在哪个位置、间距是否均匀、有没有交叉。diagram-design 里我实现了一套轻量的自动排版规则,核心思路是"行列优先 + 拓扑排序 + 分层布线"。
行列优先的意思是,默认情况下同一层的节点水平对齐、处于同一 y 坐标,层与层之间保持固定的垂直间距。架构图里最常见的结构,就是从上往下按"接入层、应用层、服务层、数据层"分层,每一层的节点都落在同一条水平基准线上。这样排出来的图天然有节奏感,不会东一个西一个。
拓扑排序用于处理有依赖关系的流程图。节点之间如果存在明确的前后依赖,就按照依赖关系确定排列顺序:被依赖的节点排在前、依赖他人的节点排在后。比如"请求进入网关 → 鉴权 → 业务处理 → 数据落库"这条链路,拓扑序列是固定的,自动布局时只需要按序列逐层下放即可。
分层布线是解决连线交叉的关键。我采用"先定层、再定列、最后定节点坐标"的三步法:先把所有节点按依赖深度分好层,再在每一层内按节点之间的连线密度排定左右顺序,最后把每层的水平坐标算出来,避免同一层内出现大跨度交叉连线。
这是 auto-layout 的核心伪代码思路:
def layout(nodes, edges): layers = topological_levels(nodes, edges) for layer in layers: order_nodes_by_connection_density(layer, edges) assign_x_coordinates(layer) assign_y_coordinates_by_layer_index(layers) adjust_spacing_to_grid(layers, grid=16)实际执行的时候,还要配合三个手工微调技巧:第一,自动排完版之后打开吸附参考线,把相邻节点的间距手动拉到统一的整数倍;第二,如果某一条跨层边线仍然交叉,优先调整起点一端的节点在同一层内的水平位置,而不是去拉终点;第三,允许"预留空白行",比如某层节点太多放不下,可以拆成两个子行,但子行之间的语义关系要在图注里写明。
3.4 第四步:把规范输出成多个格式
图表设计规范的最终价值,要体现在"能被各种场景消费"上。diagram-design 在导出层面做了三件事。
第一,JSON 导出。每张图都保存为一份结构化 JSON,包含节点坐标、尺寸、颜色、连线起止点、文本内容,这样图可以被回读、被程序分析、被自动布局算法重新排版。这个格式是我推荐所有图表项目的标准落盘格式,因为它是机器可读的。
第二,图片导出。导出 PNG 时固定 2 倍像素密度,保证在 Retina 屏幕上不模糊;导出 SVG 时保留所有图层信息,方便别人继续编辑。这里有一个坑:导出 SVG 时,不要把所有元素打平成单个路径,否则后续想改一个节点颜色都没法改。
第三,白板规格。如果你用的是在线白板或平面设计工具,就把主题配置里的颜色、字号、线宽手动手动同步为工具内的样式。虽然多一步维护成本,但值得做——因为团队里总有人不擅长代码,直接在画布上操作是最低门槛的协作方式。
4. 验收检查与常见问题排查
4.1 一张图合格吗:六个自查项
我在 diagram-design 项目里沉淀了一份"图表自查清单",每张图在交付前对照检查一遍,能挡掉大部分明显问题。
第一个自查项是语义是否统一。图里的圆柱是不是都是存储?六边形是不是都表示网关?如果同一个形状在不同模块里含义变了,就要调整。
第二个自查项是箭头方向是否正确。箭头表示的是数据或控制流的实际方向,不是"我感情上觉得应该指向的方向"。所有的依赖关系对照文档、接口设计再核对一遍。
第三个自查项是颜色是否克制。数一数图里一共用了几种功能色,超过 4 种就要考虑合并或降级。特别注意那些"为了醒目而引入的颜色",绝大多数都可以用线宽变化替代。
第四个自查项是间距是否落入网格。节点之间是否均匀、是否对齐在同一条水平线上、有没有某个节点明显偏高或偏低。一旦发现"网格不齐",读图的观感就大打折扣。
第五个自查项是交叉连线是否最简化。无法避免的交叉可以保留,但绝对不能出现"本来能避开却因为懒得调整而交叉"的情况。交叉连线是流程图的大敌,它会让读者在追踪路径时频繁丢失注意力。
第六个自查项是图例是否齐全。图越小越不需要图例,但凡是超过 6 个节点、3 种连线类型的图,右下角都应该有图例说明。
4.2 常见问题一:连线交叉失控
这是画架构图、流程图时被吐槽最多的一个问题。交叉反复出现,通常不是一条线的问题,而是布局顺序不对。
我的排查思路是:先分层,再解交叉。把整张图按依赖深度分成若干层,如果同层节点之间的连线密集,就尽量让有连线的节点在水平方向上靠得近一点。比如 A 和 B 之间有连线、A 和 C 之间也有连线、而 B 和 C 之间没有,那正确的水平顺序应该是 B、A、C 或者 C、A、B,而不是 A 居中、B 和 C 摆两边——后者必然产生跨越 A 的两条长连线。
另外一个很实用的小技巧:不要在连线上强行加拐弯。很多画图工具里,你可以手动把一个交叉线拉成绕行的路径,但绕行路径一旦离开了网格体系,后续再调整节点位置时就会变得非常难以维护。正确的做法是调整节点坐标,让连线天然走最短正交路径。
4.3 常见问题二:颜色越加越多
每个业务方都希望自己的模块在这张图上最扎眼,这是人性,挡不住。被要求"把我的模块换个醒目的颜色"的时候,我一般会做三步处理。
第一步,判断这个模块是不是主链路节点。如果是主线上的关键节点,它的"醒目"应该来自线宽和层级位置,而不是来自额外颜色。把主链路线加粗、保持功能色,观感上已经足够突出。
第二步,如果不是主链路节点,明确告诉对方:颜色只表达状态,不表达优先级。一个模块的状态可以通过左上角的状态徽标体现:绿色小圆点表示运行正常、红色表示故障、橙色表示降级。背景色保持不变,这既保留了模块的功能色语义,也满足了状态可视化的需求。
第三步,如果整个图确实需要一个额外的强调色,才引入一个"重点焦点色",并且整套图里最多用三处。这个焦点色不属于功能色,只在说明"请重点关注这里"时使用,用完就撤销。
如果做一次规范宣贯,我会特别强调一句话:颜色是语义的载体,不是情绪的载体。当颜色开始表达情绪而不是表达语义,这张图离杂乱就不远了。
4.4 常见问题三:保存之后再次打开,布局全乱了
这个问题在多人在线协作时尤其常见。原因是大家使用的工具版本不同、字体缺失、画布缩放比不一致,导致保存的图形元数据在重新打开时被工具自动调整了。
我的建议很直接:重要图表的"源文件"和"交付物"要分离。源文件用 JSON + SVG 双格式保存,SVG 是最终视觉交付物,JSON 是结构数据。在线协作画图时,每次交付前导出一份带版本号的快照,覆盖水印和创建日期。至于那些很复杂的自动布局项目,则在打开时必须重新跑一次 auto-layout,而不是依赖上次保存的视觉坐标。
另外,文字内容千万不要直接写在画布的图形内部没有边界的情况下就保存。要有统一的文本容器:所有文本长度超过节点宽度时,要么截断为省略号,要么自动换行,绝对不能出现文本溢出节点边框的情况。这个问题我在实际项目里遇到过很多次——画的时候好好的,换一台电脑打开,字体变了、文字变长了,直接溢出,丑到没法看。
5. 再往前走一步:让图表设计活起来
5.1 从静态图到数据驱动
我最早做 diagram-design 时,只是为了让团队画图更统一。但做到后面发现,光有规范还不够——图表里最有价值的信息其实是结构本身。如果能把图里的节点、连线、依赖关系变成可以被程序读取的数据,能做的事情就完全不一样了。
实现思路很直接:每张图保存一份 JSON 数据,格式是{ nodes: [...], edges: [...] }。nodes 里记录每个节点的 id、名称、类型、坐标、样式;edges 里记录每条连线的起点、终点、线型、标签。这个 JSON 既可以被前端渲染引擎直接消费,跑一套模板就能生成 Web 版图表;也可以被脚本分析,自动检测"是否存在循环依赖""是否存在两个节点之间重复连线"这种结构问题。
我在某跨平台系统上做过一个实验:把系统架构图导出的 JSON 交给一个脚本解析,脚本自动找出所有跨层调用,并且生成了一个风险报告。这个能力在纯手工画图时代是想都不敢想的。
5.2 从个人资产到团队资产
diagram-design 演进到第二阶段时,我发现单靠一份 JSON 配置还不够——因为团队里的图会持续增加,而每个人引用配置的方式可能不一样。有的同学是从模板库拖节点,有的同学是直接打开 JSON 改,还有的同学是从旧图复制节点再改文字。这三种方式本质上都正确,但产出的图会逐渐出现细微差异。
破局办法是把图元模板、主题配置、布局规则统一纳入团队资产库管理,就像前端团队管理组件库那样。图元模板更新一个样式,所有引用了这套模板的图都能同步升级。某团队的架构图资产库里,服务节点模板从最初只有"矩形+文字",迭代到后来支持"带状态徽标+带图标+带占位符"的完整形态,而所有历史图中的服务节点都因为模板升级自动获得了新能力,没有手工返工过一张图。
这个模式非常值得复制到任何需要多人协作的图表场景。一套模板,一份配置,一个资产库,让图表从"个人手绘产物"变成"团队基础设施的一部分"。
5.3 继续扩展的三个方向
我目前打算在 diagram-design 里继续推进的方向有三个。
第一个方向是无障碍与配色检测。自动计算一组节点配色的对比度,检查是否符合基本的无障碍阅读标准。比如浅色背景上的文字对比度、色弱人群能否区分主色和状态色。图表不只是给开发看的,也要能给不同视觉能力的人看,这个方向值得投入。
第二个方向是AI 辅助布局。用语言描述"把网关放中间、数据库放底层、用户入口放左边",系统自动生成对应的初始布局。这不是遥不可及的事,有了结构化的节点数据和连边关系,布局算法本身就是套规则,AI 主要解决的是"从自然语言到结构化描述"的映射问题。
第三个方向是图表组件的代码化。把图元模板、主题配置进一步抽象成前端组件,让架构图和流程图可以直接渲染为 Web 页面的一部分。这样从工具体系到前端展示,整个链路都保持同一个信息源,不会出现"图里画的跟线上跑的"不一致。
图表设计这件事,看起来是小细节,但它内嵌在整个团队的协作链路里。一套好的 diagram-design 方案,它不仅仅是让图变得好看了,更是让"传递复杂结构信息"这件事变得可靠、可复用、可演进。我个人在实际操作里的最大体会是:起点不在于挑选多么高级的工具,而在于先定规则,再把规则变成一套大家都能用、愿意用的资产——这一步走扎实了,后面所有环节都会顺很多。