1. 为什么“画图”这件事值得单独做一个设计系统先说说我为什么会盯上 diagram-design 这个方向。过去几年里我参与过不少技术文档、产品白皮书、内部培训材料的制作几乎每一个项目都绕不开画图这件事。流程图、架构图、时序图、状态机、数据流图甚至简单的对比示意图需求量远比想象中大。但真正让我头疼的不是“画不出来”而是“画出来不统一”。一个团队里A 同学用某在线工具画了一套架构图B 同学用本地软件画了流程图C 同学直接截图 PPT 里的手绘风示意图。三张图放在同一份文档里配色、线宽、字体、圆角、箭头样式全都不一样读者一眼就能看出这是“拼凑”出来的内容。更麻烦的是当产品迭代、架构调整时这些图散落在不同工具、不同人的电脑里改一张图要花半小时找源文件。diagram-design 这个项目标题本质上要解决的就是这个问题把“画图”从一次性手工劳动变成一套可复用、可维护、有统一视觉语言的设计系统。它不是一个具体的绘图工具而是一套围绕图表设计的规范、组件、模板和协作流程的集合。说得直白一点它让团队里任何人画出来的图都像同一个人画的。这套东西适合谁如果你是技术文档工程师、产品经理、架构师、技术博主或者任何一个需要频繁输出图表的人diagram-design 的思路都值得参考。哪怕你只是偶尔画几张图建立一套自己的图表设计规范也能让输出质量提升一个档次。接下来我会从整体设计思路、核心细节、实操过程、常见问题几个维度把这套东西拆开讲清楚。2. 整体设计思路与方案选型2.1 核心问题拆解图表为什么总是“丑得五花八门”在动手建立任何规范之前我先做了一件事收集团队里过去半年产出的所有图表大概有 200 多张然后按来源、工具、风格、用途分类。分类结果很说明问题。问题类型出现频率典型表现配色不统一87%同一文档中蓝色有 5 种不同色值字体混乱72%中文用宋体、英文用 Arial、代码用 Consolas线宽与箭头不一致65%有的箭头粗、有的细圆角半径从 2px 到 12px 都有布局逻辑混乱58%有的从左到右有的从上到下没有统一方向缺少图例与标注43%读者需要猜某个颜色或形状代表什么源文件丢失39%只有导出图片没有可编辑源文件这些问题的根源不是“审美差”而是缺少一套约束。人天生倾向于每次做决定时重新选择今天觉得这个蓝色好看明天觉得那个绿色不错积累下来就是灾难。diagram-design 的第一个设计原则就是把重复决策变成默认选项。2.2 方案选型为什么选择“规范模板工具链”三层结构市面上解决图表统一性的方案大致有三种。第一种是强制所有人用同一个在线工具比如某协作白板平台。第二种是制定一份详细的视觉规范文档靠人自觉遵守。第三种是建立一套“规范模板工具链”的组合体系。我最终选择了第三种理由如下。强制统一工具的问题在于不同场景对图表的需求差异很大。架构图需要精确的层级关系流程图需要灵活的分支时序图需要严格的时间轴一个工具很难在所有场景都做到最优。而且在线工具的网络依赖、数据安全、导出质量都是潜在风险。纯规范文档的问题更明显人是有惰性的一份 50 页的规范文档真正会逐条对照执行的人不到两成。“规范模板工具链”的组合则兼顾了灵活性和约束力。规范定义“什么是对的”模板提供“开箱即用的起点”工具链负责“自动检查和转换”。三者配合既不会把人的创造力锁死又能保证输出的一致性。具体来说规范层包含色彩系统、字体系统、间距系统、图标系统模板层包含常见图表类型的源文件模板工具链层包含格式转换脚本、批量导出脚本、一致性检查脚本。2.3 视觉语言设计从“好看”到“可读”的取舍很多人在做图表设计时第一反应是“怎么让它好看”。但 diagram-design 的核心目标不是好看而是可读。一张架构图读者能在 5 秒内找到核心模块比配色惊艳重要得多。所以我在设计视觉语言时遵循了三条优先级信息层级 视觉一致性 美观度。信息层级怎么体现靠大小、粗细、颜色深浅、位置关系。核心模块用更大的尺寸和更深的颜色辅助模块用更小的尺寸和更浅的颜色。视觉一致性靠的是“设计令牌”的概念把所有颜色、字号、间距、圆角都定义成变量任何图表都从这些变量里取值不允许出现“随手选一个颜色”的情况。美观度反而是最后才考虑的因为当信息层级清晰、视觉一致时图表自然就不会难看。这里有一个我踩过的坑一开始我花了大量时间设计一套非常精致的配色方案结果发现团队里没人用因为“记不住色值”。后来我把配色方案简化成 6 个主色加 4 个中性色每个颜色都有明确的语义比如蓝色代表数据层、绿色代表服务层、橙色代表外部依赖大家反而用得很顺手。颜色不在多在于每个颜色都有明确的含义。3. 核心细节解析与实操要点3.1 色彩系统64 配色法的定义与使用规则色彩系统是 diagram-design 里最基础也最重要的部分。我采用的是 6 个语义色加 4 个中性色的结构。6 个语义色分别对应数据层、服务层、外部依赖、用户交互、基础设施、警告异常。4 个中性色分别是背景色、边框色、主文本色、辅助文本色。每个语义色都有三个变体主色、浅色背景、深色边框。主色用于填充核心形状浅色背景用于大面积区域深色边框用于强调边界。这样设计的好处是同一个语义色可以在不同场景下灵活使用而不需要额外定义新颜色。语义主色浅色背景深色边框使用场景数据层#3B82F6#EFF6FF#1D4ED8数据库、缓存、消息队列服务层#10B981#ECFDF5#047857微服务、API 网关、业务逻辑外部依赖#F59E0B#FFFBEB#B45309第三方接口、外部系统用户交互#8B5CF6#F5F3FF#6D28D9前端页面、客户端、用户操作基础设施#6B7280#F9FAFB#374151服务器、容器、网络警告异常#EF4444#FEF2F2#B91C1C错误处理、降级、熔断实操中有一个关键点不要直接使用十六进制色值而是把色值定义成设计令牌。比如在 CSS 里定义--color-data-primary: #3B82F6在绘图工具里定义“数据层主色”样式。这样当需要调整配色时只需要改一处定义所有图表自动更新。我试过在 30 多张图里手动替换色值花了整整一个下午而用设计令牌只需要 5 分钟。注意语义色的数量不要超过 8 个。超过之后人脑很难快速建立颜色与含义的映射关系反而会增加认知负担。如果确实需要更多分类优先考虑用形状、图标或文字标注来区分而不是增加颜色。3.2 字体与排版中文图表里的字体陷阱字体是图表设计里最容易被忽视、也最容易出问题的部分。中文图表的字体问题比英文更复杂因为中文字体文件大、渲染差异明显、跨平台兼容性差。我见过太多图表在设计师电脑上显示正常到了别人电脑上就变成宋体或乱码。我的解决方案是主字体用系统默认无衬线字体代码和数字用等宽字体并且明确指定字体回退链。具体来说中文优先使用“思源黑体”或“苹方”英文和数字优先使用“Inter”或“Roboto”代码使用“JetBrains Mono”或“Consolas”。字体回退链写成Inter, Roboto, PingFang SC, Microsoft YaHei, sans-serif。这样即使某个字体缺失也能回退到系统默认字体不会出现乱码。字号方面我定义了 5 个层级图表标题 18px、模块标题 14px、正文标注 12px、辅助说明 10px、图例 10px。字号层级不要太多3 到 5 个足够。行高统一设置为字号的 1.5 倍这样文字不会显得拥挤。字重只用两个常规 400 和加粗 600。不要用 300 或 700因为不同字体对字重的渲染差异很大容易导致视觉不一致。还有一个细节中文和英文混排时中英文之间要加一个空格。这个规则看起来很小但对可读性影响很大。比如“使用 Redis 缓存”比“使用Redis缓存”读起来舒服得多。在绘图工具里这个空格需要手动加但在 Markdown 或代码注释里可以用脚本自动处理。3.3 形状与连线圆角、线宽、箭头的标准化形状和连线是图表的“骨架”它们的统一性直接决定了图表看起来是否专业。我定义的规则如下所有矩形圆角半径统一为 4px圆形和椭圆不设圆角菱形和六边形用于特殊语义。形状的边框线宽统一为 1.5px连线线宽统一为 1.5px强调连线可以用 2.5px。箭头样式统一为“实心三角”大小为中号。为什么圆角是 4px 而不是 8px 或 12px因为 4px 在大多数屏幕和打印尺寸下都能保持清晰不会因为圆角太大而显得“卡通化”。线宽 1.5px 是一个折中值1px 在高分屏上太细2px 又显得笨重。箭头用实心三角而不是开放式箭头是因为实心箭头在缩小后仍然清晰可辨。连线还有一个容易忽略的点连线不要穿过形状。很多绘图工具默认连线是直线连接会直接穿过中间的形状。正确的做法是使用“正交连线”或“曲线连线”让连线绕开形状。如果工具不支持自动绕行就手动添加转折点。我见过一张架构图一条连线穿过了三个模块读者根本分不清它到底连接的是哪两个。提示在定义形状样式时同时定义“选中状态”和“悬停状态”的样式。虽然静态图表不需要交互但如果你要把图表嵌入网页或文档交互状态的一致性同样重要。选中状态可以用加深边框或添加外发光来表示悬停状态可以用轻微的背景色变化。3.4 布局与间距8px 网格系统的落地方法布局混乱是图表“看起来不专业”的最大原因之一。解决布局问题最有效的方法是引入网格系统。我采用的是 8px 网格也就是说所有元素的位置和尺寸都必须是 8 的倍数。为什么是 8 而不是 10 或 12因为 8 是大多数屏幕分辨率和图标尺寸的公约数16、24、32、48 都是 8 的倍数缩放时不会出现半像素问题。具体落地时我会在绘图工具里打开网格显示设置网格间距为 8px并开启“对齐到网格”。模块之间的水平间距用 24px 或 32px垂直间距用 16px 或 24px。模块内部的文字与边框间距用 8px 或 12px。整个图表的四周留白用 32px 或 48px。这些数值不是随便定的而是经过多次实际排版后总结出来的“舒适区”。布局方向也需要统一。架构图统一从左到右或从上到下流程图统一从上到下时序图统一从左到右。不要在一张图里混用多个方向否则读者的视线会来回跳跃增加理解成本。如果一张图确实需要多个方向就用分组框或背景色块把不同方向的区域分开。4. 实操过程与核心环节实现4.1 从零搭建一套图表模板库的完整步骤搭建模板库是 diagram-design 落地的第一步。我的做法是先梳理团队最常用的图表类型然后为每种类型制作 2 到 3 个模板。梳理结果显示最常用的图表类型有 6 种系统架构图、业务流程图、数据流图、状态机图、时序图、对比示意图。每种类型制作 3 个模板总共 18 个模板基本覆盖了 90% 的日常需求。制作模板的具体步骤如下。第一步确定画布尺寸。我统一使用 1920x1080 像素的画布这个尺寸在大多数文档和演示场景下都够用导出时再按需缩放。第二步建立图层结构。每个模板包含背景层、网格层、内容层、标注层四个图层。背景层放背景色和分组框网格层放参考线内容层放形状和连线标注层放文字说明和图例。第三步定义样式库。把前面讲的色彩、字体、形状、连线样式全部定义成命名样式方便一键应用。第四步制作示例内容。每个模板里放一个完整的示例展示该类型图表的典型用法。第五步导出为模板文件。根据使用的工具不同导出为对应的模板格式比如 .drawio、.fig、.sketch 或 .svg。这里有一个实操心得模板不要做得太“满”。我一开始做的架构图模板里放了 20 多个模块结果大家觉得太复杂反而不用。后来我改成只放 5 个核心模块加 2 个外部依赖大家觉得“这个我能改”使用率立刻上去了。模板的作用是提供起点不是提供终点。4.2 用脚本批量检查图表一致性的方法模板库建好之后下一个问题是怎么保证大家真的按规范来靠人眼检查 200 张图是不现实的。我的做法是写一个简单的检查脚本自动扫描图表源文件找出不符合规范的地方。脚本的核心逻辑是解析图表文件大多数绘图工具都支持导出为 XML 或 JSON 格式然后检查以下几项颜色是否在允许的色值列表里、字体是否在允许的字体列表里、线宽是否为 1.5px 或 2.5px、圆角半径是否为 4px、元素位置是否为 8 的倍数。任何一项不符合就在报告里标记出来。import xml.etree.ElementTree as ET ALLOWED_COLORS {#3B82F6, #10B981, #F59E0B, #8B5CF6, #6B7280, #EF4444, #EFF6FF, #ECFDF5, #FFFBEB, #F5F3FF, #F9FAFB, #FEF2F2} ALLOWED_FONTS {Inter, Roboto, PingFang SC, Microsoft YaHei, JetBrains Mono} ALLOWED_LINE_WIDTHS {1.5, 2.5} ALLOWED_RADIUS {4} GRID_SIZE 8 def check_diagram(file_path): tree ET.parse(file_path) root tree.getroot() issues [] for elem in root.iter(): color elem.get(fill) or elem.get(stroke) if color and color.upper() not in ALLOWED_COLORS: issues.append(f颜色不合规: {color} 在元素 {elem.tag}) font elem.get(font-family) if font and font not in ALLOWED_FONTS: issues.append(f字体不合规: {font} 在元素 {elem.tag}) width elem.get(stroke-width) if width and float(width) not in ALLOWED_LINE_WIDTHS: issues.append(f线宽不合规: {width} 在元素 {elem.tag}) x elem.get(x) if x and float(x) % GRID_SIZE ! 0: issues.append(f位置未对齐网格: x{x} 在元素 {elem.tag}) return issues这个脚本我跑了大概 200 张图发现了 300 多个问题其中颜色不合规占了 60%位置未对齐网格占了 25%。把报告发给团队后大家改了一轮整体一致性明显提升。脚本不需要写得很复杂能覆盖 80% 的常见问题就足够了。4.3 图表源文件管理与版本控制方案图表源文件的管理是另一个容易被忽视的环节。很多团队的图表源文件散落在各人的电脑里时间一长就找不到了。我的方案是所有图表源文件统一放在一个 Git 仓库里按项目或文档分类存放每次修改都提交 commit。目录结构大概是这样的diagrams/项目名/图表类型/图表名称.drawio。比如diagrams/支付系统/架构图/整体架构.drawio。每个图表旁边放一个同名的.png或.svg导出文件方便在文档里直接引用。提交 commit 时要求写清楚修改内容比如“更新支付系统架构图新增风控模块”。这样做的好处有三个。第一任何历史版本都可以回溯改错了可以回滚。第二多人协作时不会互相覆盖Git 会自动合并或提示冲突。第三图表和文档可以放在同一个仓库里保持同步更新。我试过把图表和文档分开管理结果文档更新了图表没更新读者看到的还是旧图非常尴尬。注意二进制格式的图表文件如 .drawio、.fig在 Git 里无法 diff只能看到“文件已更改”。如果团队对版本对比有需求可以同时导出 SVG 格式SVG 是文本格式可以看到具体的修改内容。5. 常见问题与排查技巧实录5.1 图表导出后模糊或失真的原因与解决图表导出后模糊是最常见的问题之一。原因通常有三个导出分辨率不够、矢量图被栅格化、字体没有嵌入。导出分辨率不够的情况最常见很多人直接导出 PNG 默认尺寸放到文档里一放大就模糊了。解决方法是在导出时设置 2x 或 3x 分辨率或者直接导出 SVG 矢量图。矢量图被栅格化的情况通常发生在把图表粘贴到 Word 或 PPT 里时。这些软件有时会自动把矢量图转换成位图导致放大后模糊。解决方法是导出为 EMF 或 SVG 格式然后在 Word 或 PPT 里插入“图片”而不是直接粘贴。如果必须粘贴粘贴后右键选择“保留源格式”。字体没有嵌入的情况在跨平台分享时很常见。比如你在 Mac 上用苹方字体画图导出 PDF 时没有嵌入字体到了 Windows 上就会用宋体替代排版全乱。解决方法是在导出 PDF 时勾选“嵌入字体”或者直接导出为 SVG 并把文字转换为路径。文字转路径的缺点是不能再编辑文字所以建议保留一份可编辑源文件。问题现象可能原因解决方法放大后模糊导出分辨率不够导出 2x/3x PNG 或 SVG粘贴到文档后模糊矢量图被栅格化插入图片文件而非直接粘贴字体变了字体未嵌入导出时嵌入字体或文字转路径颜色变了色彩配置文件不一致统一使用 sRGB 色彩配置线条粗细变了缩放时未保持比例导出时锁定宽高比5.2 多人协作时图表风格冲突的协调方法多人协作时即使有规范不同人画出来的图还是会有差异。我遇到过最典型的情况是两个人画同一张架构图的不同部分一个人习惯用圆角矩形另一个人习惯用直角矩形拼在一起非常违和。协调方法有三个层次。第一层是预防。在项目开始前把模板和规范发给所有参与者并要求大家先花 10 分钟熟悉。我通常会做一个 5 分钟的录屏演示怎么从模板创建图表、怎么应用样式、怎么导出。这个投入非常值得能避免后面大量的返工。第二层是检查。在图表合并到主文档之前用前面提到的检查脚本跑一遍把不合规的地方改掉。如果脚本覆盖不了的问题就人工过一遍重点看形状风格、连线风格、标注风格是否统一。第三层是仲裁。如果两个人对某个设计决策有分歧比如一个人觉得应该用蓝色表示数据层另一个人觉得应该用绿色那就回到规范文档看规范里怎么定义的。如果规范里没有定义就由一个人拍板决定并更新规范文档。不要让分歧悬而不决否则每次遇到类似问题都要争论一遍。5.3 图表信息过载时的简化策略图表信息过载是另一个高频问题。一张图里塞了 50 个模块、80 条连线读者根本看不清。我判断信息是否过载的标准很简单如果一张图在正常阅读距离下需要超过 10 秒才能找到核心模块那就是过载了。简化策略有四种。第一种是分层展示把一张大图拆成“总览图细节图”。总览图只放核心模块和主要连线细节图展开某个模块的内部结构。第二种是折叠次要信息把不重要的模块用灰色或虚线表示或者放到附录里。第三种是改变表达方式有些信息用表格比用图更清晰不要强行画成图。第四种是删减如果某个模块在整张图里只出现一次且不影响理解就删掉它。我个人的经验是一张图里的模块数量控制在 7 到 12 个之间最舒适连线数量控制在 15 条以内。超过这个范围就要考虑拆图了。拆图不是失败而是对读者负责。5.4 常见问题速查表问题排查思路解决方案图表打开后样式丢失检查样式是内嵌还是引用将样式内嵌到文件中连线穿过形状检查连线类型改用正交连线或手动加转折点文字溢出形状检查形状尺寸和字号增大形状或缩小字号导出文件过大检查是否嵌入了大图压缩图片或改用 SVG颜色在打印时失真检查色彩模式改用 CMYK 模式导出图表在不同软件打开不一致检查文件格式兼容性统一使用 SVG 或 PDF修改后忘记更新导出文件建立自动化导出流程用脚本监听源文件变化自动导出6. 工具链与自动化让规范“自动生效”6.1 绘图工具选型的三个核心考量工具选型是 diagram-design 落地时绕不开的问题。我评估过不少绘图工具最终的选择标准有三个是否支持样式库、是否支持脚本扩展、是否支持版本控制友好的文件格式。支持样式库意味着可以把前面定义的色彩、字体、形状样式保存下来一键应用。不支持样式库的工具每次画图都要手动设置效率低且容易出错。支持脚本扩展意味着可以用代码批量处理图表比如批量导出、批量检查、批量替换颜色。不支持脚本扩展的工具所有操作都要手动完成规模化时非常痛苦。支持版本控制友好的文件格式意味着文件是文本格式或结构化格式可以 diff、可以合并。二进制格式的文件在协作时很麻烦。基于这三个标准我最终选择了支持 XML 格式的绘图工具作为主力配合 SVG 作为通用交换格式。XML 格式可以脚本处理SVG 格式可以在任何地方打开。两者配合基本覆盖了所有场景。6.2 自动化导出与格式转换脚本手动导出图表是一件重复且容易出错的事。我写了一个自动化脚本监听图表源文件的变化一旦有修改就自动导出为 PNG 和 SVG。脚本用 Python 的 watchdog 库监听文件系统事件用绘图工具的命令行接口执行导出。import time from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler import subprocess class DiagramHandler(FileSystemEventHandler): def on_modified(self, event): if event.src_path.endswith(.drawio): print(f检测到修改: {event.src_path}) export_png(event.src_path) export_svg(event.src_path) def export_png(source): target source.replace(.drawio, .png) subprocess.run([drawio, --export, --format, png, --scale, 2, --output, target, source]) def export_svg(source): target source.replace(.drawio, .svg) subprocess.run([drawio, --export, --format, svg, --output, target, source]) if __name__ __main__: observer Observer() observer.schedule(DiagramHandler(), path./diagrams, recursiveTrue) observer.start() try: while True: time.sleep(1) except KeyboardInterrupt: observer.stop() observer.join()这个脚本跑起来之后我只需要专注于编辑源文件导出的事情完全不用管。导出后的 PNG 和 SVG 会自动放在源文件旁边文档里直接引用即可。实测下来每天能省下至少 20 分钟的导出时间而且再也不会出现“忘记导出”的情况。6.3 与文档系统的集成方式图表最终是要放到文档里的。如果图表和文档是分离的更新图表后还要手动替换文档里的图片很容易遗漏。我的做法是把图表源文件和文档放在同一个仓库里用相对路径引用导出的 SVG 文件。这样更新图表后文档里的图片自动更新。如果文档系统支持嵌入 SVG就直接嵌入 SVG。SVG 的好处是矢量、清晰、文件小、可以搜索文字。如果文档系统不支持 SVG就嵌入 PNG但要用 2x 分辨率导出。我试过在 Markdown 文档里嵌入 SVG效果很好放大缩小都不失真而且可以用 CSS 控制样式。对于需要频繁更新的图表我还会在文档里加一个“图表版本”标注比如“架构图 v2.3更新于 2024-06”。这样读者能知道这张图是不是最新的也方便追溯历史版本。7. 我在这套体系里踩过的坑和总结的经验回过头看diagram-design 这套东西从想法到落地大概花了三个月时间。中间踩过的坑不少有几个印象特别深。第一个坑是过度设计。一开始我想做一套“完美”的规范定义了 20 多种颜色、10 多种字体、30 多种形状。结果团队里没人记得住用的时候还是随手选。后来砍到 6 个语义色、5 个字号、4 种形状使用率反而上去了。规范不是越全越好而是越容易记住越好。第二个坑是忽视工具限制。我一开始选了一个功能很强大的绘图工具但它不支持样式库每次画图都要手动设置样式。后来换了一个支持样式库的工具效率提升了一倍。工具选型一定要先看它能不能支撑你的工作流而不是看它功能多不多。第三个坑是缺少反馈机制。规范发布后我没有及时收集使用反馈导致有些规范在实际操作中很不方便但大家默默忍受没有提出来。后来我加了一个简单的反馈表每季度收集一次意见规范才逐渐完善。规范是活的需要不断迭代。如果让我给正在考虑做类似事情的同行一个建议那就是先从小范围开始不要一上来就搞大而全的体系。先选一个最常用的图表类型做一套模板和规范用起来收集反馈再逐步扩展到其他类型。这样风险小、见效快也更容易获得团队的支持。