如果你画过架构图,大概率经历过这种尴尬:方案讲得头头是道,图一放出来,评审现场直接就尬住了。框线对不齐、字体发虚、配色像调色盘打翻,逻辑再严谨,也很难让人相信你“考虑周全”。我从前端转到基建、又在一线带过几年团队,对这种“图不给力”的痛太有体会了。最近在GitHub上刷到一个叫 diagram-design 的源码项目,一句话就把我勾住了:告别粗糙架构图,纯HTML+SVG实现设计师也认可的出版级图解。
这项目不是又一个拖拽画图工具,而是一套把SVG绘图这件事做到工程化、规范化的完善方案。我把它拉下来仔细读了一遍,跑了demo,还拿团队真实的系统架构图试了水,确实能打。接下来的篇幅,我会从设计思路、源码机制、实操落地和避坑经验四个维度拆一拆这个项目,并把其中最值得迁移的部分单独抽出来讲透。不管你是前端、后端还是经常要画方案图的普通开发,这篇文章都能让你少走不少弯路。
1. diagram-design到底是什么、解决什么问题
1.1 被架构图丑哭的评审现场
先说个真实场景。之前我带一个中台项目,技术方案写了三周,核心链路设计得自认为很完善。到了评审会,打开图的那一瞬间,我就看到几个业务方在偷偷皱眉——倒不是方案有问题,是图真的太糙了。流程框大小不一,箭头歪歪扭扭,配色是draw.io默认的“蜜汁撞色”,字体在小屏幕上糊成一团。结果前十分钟全在解释“这个框代表什么”“这条线为什么是虚线”,真正该讨论的架构决策反而没时间聊。
这种痛我估计很多人都经历过。工具本身没有错,draw.io、Visio、ProcessOn都能画图,问题在于默认美术水平和我们大脑里“专业”的期望差得太远。而专业设计师做的图,看似只是“好看”,其实是字体、间距、对齐、配色、留白这些细节在统一发力。
diagram-design这个项目最打动我的点,就是它把这些“审美细节”全部变成了可复用的代码参数。它不逼你手动调,而是从底层帮你把美术规范定死,让普通人也能画出一眼看去就很专业的图。
1.2 项目定位:不是画布工具,是图解渲染方案
如果你以为diagram-design是又一个在线画图工具,那就理解偏了。它本质上是一套基于HTML和SVG的图解渲染方案:你通过结构化的数据或标签去描述“图里面有什么”,它负责把它画成一张高完成度的矢量图。
在这个方案里,有几个核心概念:画布、节点、连线、主题。画布定义坐标系和尺寸;节点是图里的“框图”和“文字块”;连线表达节点之间的关系;主题则统一控制颜色、圆角、阴影、字体等视觉参数。这种设计带来的最大优势是:图不再是一张不可编辑的位图,而是纯文本描述出来的结构化产物。
只要描述图的数据没有变,谁来渲染、用什么主题渲染,出来的都是同一张规范图。这解决了团队协作时“每个人画的图风格都不一样”的世纪难题。对开发团队来说,它还可以直接嵌入网页、注入自动化文档流水线,甚至做成动态可视化图表。这是传统画图工具做不到的。
1.3 快速跑起来:从拉取源码到渲染第一张图
我实际跑了一遍,流程很顺。先把仓库克隆到本地,然后在项目根目录起一个静态服务就行。
git clone <diagram-design仓库地址> cd diagram-design python3 -m http.server 8000浏览器打开http://localhost:8000,就能看到项目自带的demo页面。页面里有现成的架构图、流程图、拓扑图示例,你可以直接在浏览器里查看源码,找到SVG对应的节点定义。比如demo里一个最简单的节点,长这样:
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg"> <rect x="100" y="100" width="200" height="80" rx="8" fill="#fff" stroke="#4F6AF6" stroke-width="1.5"/> <text x="200" y="138" text-anchor="middle" font-size="14" fill="#333">核心服务</text> </svg>这段代码画了一个宽200、高80的圆角矩形,里面居中写了一行字。看起来简单,但它已经具备了出版级图解的雏形:圆角克制、描边细致、文字对齐精确。后面我会把如何从这个小节点扩展到完整架构图一步步讲清楚。
2. 为什么选择纯HTML+SVG这条路
2.1 先聊聊其他方案的坑
很多人画架构图的第一反应是打开画图工具,或者用Canvas类库。这两种思路都有天花板。传统画图工具最大的问题是“不可编程”,图画完就定了,后期改动、批量生成、版本对比都很难做。Canvas方案虽然可以编程,但它是位图渲染模型,画出来的东西是像素,文字不能选中、无法检索,放大到一定程度还会发虚。
我在项目里也踩过Canvas的坑。早前做监控大屏,用Canvas画拓扑图,40个节点还流畅,到200个节点加动画后,帧率掉得厉害。而且业务方反馈“图里的字不能复制”,没有很好的办法,只能改方案。后来换SVG,文字天然就是文本节点,鼠标一拖就能选中,这个体验上的差距是位图方案弥补不了的。
还有一类方案是直接用HTML+CSS拼布局,用div模拟图块、用border画线。这种做法做做简单示意图还行,一旦涉及复杂连接线、曲线、锚点,CSS就会非常吃力,几乎没有可行性。
2.2 SVG的本质优势:图形本身就是DOM节点
SVG最重要的特点是:所有图形元素都是DOM节点。这意味着你可以用CSS控制它的样式,用JavaScript操作它的结构,用浏览器开发者工具直接审查它的属性。调试流程和调试普通网页完全一致,对前端来说几乎没有学习门槛。
另一个很实际的优势是矢量缩放。无论图在手机小屏还是4K大屏上展示,SVG都能保持边缘锐利。出版场景下,SVG可以直接转成PDF或者高分辨率PNG,打印300DPI依然清晰。这一点普通位图做不到,Canvas也做不到。
SVG还天然支持一些前端生态的附属能力:动画、事件绑定、无障碍标签、ARIA标注。比如你可以给一个节点加上aria-label,让读屏软件读出“支付服务”这个名字,这对团队内部文档的可访问性是很大的加分项。
2.3 工程化与协作价值是你没想到的
大多数人选画图方案时只会考虑“能不能画出来”,很少考虑“这个图能不能进代码仓库、能不能被评审”。diagram-design最聪明的地方,就是把图变成了纯文本的SVG代码。
代码就意味着可以进Git,可以diff。团队里任何一个人改了架构图,提交记录里都能看清改了什么——是加了一个服务框,还是换了一条连线的颜色。这个特性在文档评审、架构治理场景下价值极高。以前看图只能靠肉眼对比两版图片,现在可以直接看代码变更,精度完全不一样。
主题变量也让“设计师认可”这件事变得可实现。设计师定好一套色彩、圆角、阴影规范,开发者把规范落成CSS变量或者主题配置文件,所有人画出来的图都是同一套视觉语言。不再出现“这个人偏好蓝色、那个人喜欢绿色”的混乱局面。
3. 源码级拆解:diagram-design的核心实现机制
3.1 画布坐标系与viewBox设计
看源码首先会注意到整个画布根节点上的viewBox属性。viewBox定义了SVG内部的虚拟坐标系,比如viewBox="0 0 1200 800"表示图内部空间是1200像素宽、800像素高。浏览器会根据容器大小自动缩放这个坐标系,所以图在任何屏幕上都不会拉伸变形。
这里值得学习的一个设计是:diagram-design在画图时并不会让使用者直接面向屏幕像素操作,而是面向“逻辑坐标”。比如你想在画布中间放一个节点,只需要根据画布的逻辑尺寸计算坐标,不用关心最终渲染设备的分辨率。这样做的好处是把“布局”和“呈现”解耦了,图在什么设备上看,效果都保持一致。
我在复刻这个设计时踩过一个坑:忘记设置viewBox,直接用了width和height。结果在小屏设备上SVG溢出,大屏上边缘又留白太多。后来把viewBox固定为设计稿尺寸,再把width设成100%,问题立刻解决。
3.2 节点与容器:圆角、阴影、边框背后的“审美参数”
diagram-design里节点的视觉呈现非常讲究。以矩形节点为例,核心参数就几个:rx圆角半径、fill填充色、stroke描边色、stroke-width描边宽度。但不同的组合方式,出来的气质完全不一样。
源码里节点默认采用白色填充、浅灰描边、中等圆角的组合,这个组合最接近现代设计规范中的卡片风格。圆角半径一般取8到12像素,太小显得生硬,太大又丧失严肃感。阴影则是通过SVG的filter实现的,默认模糊半径不会太大,阴影颜色是半透明的黑色,而不是纯黑,这样阴影会显得柔和,不“脏”。
我并排对比过rx=4和rx=12的节点效果,结论是:如果是技术架构图,8像素是比较安全的中间值;如果是面向管理层的汇报图,可以加大到12,视觉上更亲和。源码里把这些参数做成主题变量后,切换风格只是改两个变量的事,完全不需要重画。
3.3 连线的三种画法与布局算法
图的高级感,一半取决于节点,另一半取决于连线。diagram-design源码里将连线分成三种形态:直线连接、折线连接、曲线连接。直线适合表达强关联,折线适合表达流程走向,曲线用来表达复杂的网状关系时最优雅。
曲线连线的实现并不神秘,核心就是贝塞尔曲线路径。举个例子,如果要从起始点(x1, y1)连接到结束点(x2, y2),一条横向弧线可以写成:
<path d="M x1 y1 C x1+offset y1, x2-offset y2, x2 y2" stroke="#888" fill="none"/>offset控制了曲线在起点和终点附近的弯曲程度。源码中会根据两个节点的相对位置和连线方向来动态计算offset:如果节点是左右排列,offset用水平方向;如果是上下排列,offset用垂直方向。这个逻辑看似简单,却是整个图看起来“顺不顺眼”的关键。
更值得借鉴的是连接点的锚定规则。diagram-design没有让连线从节点矩形的正中心穿过,而是让线从矩形边缘的“锚点”出发。这样避免线和文字重叠,整个图会显得非常干净。我第一次画连线时没有锚点概念,线直接横穿文字,效果惨不忍睹,后来照着源码改成边缘锚点,图面瞬间清爽很多。
3.4 出版级排版系统:从网格到字体的完整控制
这部分我非常推荐所有画图的人认真看。diagram-design之所以能接近“出版级”,排版细节功不可没。
首先是网格对齐。源码里所有节点坐标、尺寸都遵循一个基本网格单位,我看到的demo中是8像素,部分场景会用4像素微调。只要所有元素都落在网格线上,随便怎么看,画面都是整齐的。很多草率的图画出来歪歪扭扭,本质就是元素坐标没有落在同一个网格系统上。
其次是字体栈和字号梯度。源码里中文字体栈大概是类似"PingFang SC", "Microsoft YaHei", sans-serif的组合,西文部分是常见的系统无衬线字体。字号梯度上,默认层级是:主标题18到20、节点标题14到16、说明文字12。字重上,标题用600,正文用400,这种克制的对比让信息主次分明。
最后是行高和留白。SVG里的text不会自动换行,diagram-design在源码里提供了文本换行的处理逻辑,把长文本按最大宽度拆分成多行,行高默认是字号乘1.5。行与行之间、节点与节点之间的留白也都有最小阈值,保证画面不压抑、不拥挤。这些参数单独看都不起眼,全部叠加起来就成了“专业感”的来源。
4. 实操复现:手写一张出版级系统架构图
4.1 搭建HTML骨架与SVG画布
我们不看复杂的项目代码,先自己动手复现一张简单的系统架构图。新建一个HTML文件,加入基础骨架和SVG画布。画布逻辑尺寸设为1200宽、800高,这样有足够空间表达至少3层架构。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>diagram-design实践:出版级架构图</title> <style> body { background: #f5f6f8; display: flex; justify-content: center; padding: 40px 0; } .diagram { width: 1200px; background: #fff; border-radius: 12px; padding: 24px; box-shadow: 0 4px 20px rgba(0,0,0,0.06); } svg { width: 100%; height: auto; display: block; } </style> </head> <body> <div class="diagram"> <svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg"> <!-- 图内容写在这里 --> </svg> </div> </body> </html>画布外面套一个白色卡片容器,这是很多设计站点常用的展示手法,可以让图在预览时就显得高级。svg的width: 100%配合viewBox,确保缩放在任何宽度下不变形。
4.2 用CSS变量统一主题
diagram-design源码里把视觉参数抽成了主题变量,这个思路在纯HTML+SVG里同样适用。我们可以在<style>里定义一组CSS变量,然后在SVG元素上用var()引用。
:root { --primary: #4F6AF6; --primary-light: #EEF2FF; --text-main: #1F2329; --text-sub: #5F6B7A; --border: #D0D7E2; --bg-node: #FFFFFF; --radius: 8px; --shadow-color: rgba(31, 35, 41, 0.10); --line-color: #A3ADBB; --line-width: 1.5; --font-main: "PingFang SC", "Microsoft YaHei", -apple-system, sans-serif; }主题变量带来一个立竿见影的好处:后续所有节点都引用这些变量,如果要换一套配色,只需要改变量定义。比如公司要出深色版架构图,把--bg-node和--text-main改掉就全部同步了。这也是diagram-design源码里“主题”模块的核心思想。
4.3 写节点、连线和分组区域
接下来我给一张典型的三层架构图画几个节点。前端网关层、业务服务层、数据存储层各画一个区块,再加两条连线表示调用关系。
先看单个节点的写法。一个标准的服务节点,由矩形背景、左侧图标区、文字标题和副标题组成。为了保持代码简洁,我用<g>把几个图形元素打包成一个逻辑单元:
<g transform="translate(80, 80)"> <rect width="240" height="96" rx="8" fill="var(--bg-node)" stroke="var(--border)" stroke-width="1.5"/> <rect x="0" y="0" width="6" height="96" rx="3" fill="var(--primary)"/> <text x="28" y="42" font-size="16" font-weight="600" fill="var(--text-main)" font-family="var(--font-main)">API网关</text> <text x="28" y="66" font-size="12" fill="var(--text-sub)" font-family="var(--font-main)">统一流量入口,鉴权与路由</text> </g>左边竖着的一条彩色矩形是diagram-design里很常见的一种设计:用一个小的强调色块给节点增加视觉重心,避免节点看起来像“光秃秃的盒子”。这种做法简单,但专业感提升非常明显。
再画另外两个服务,结构类似,只是坐标不同。然后画一条从API网关指向业务服务的曲线连线,用贝塞尔曲线让路径平滑:
<path d="M 320 128 C 420 128, 420 128, 520 128" stroke="var(--line-color)" stroke-width="1.5" fill="none"/> <circle cx="520" cy="128" r="4" fill="var(--primary)"/>路径在水平方向平滑过渡,终点加一个小圆点作为箭头端口的视觉提示。这里如果你想要真正的箭头,可以在末尾加一个<polygon>三角形,或者使用SVG的marker-end属性。diagram-design源码里两种方式都有,简单场景用marker更省事,追求精细控制就自己画箭头。
4.4 导出与发布:让矢量图落到报告和网页里
图画完之后,下一步是怎么用。由于整个架构图就是SVG,嵌入网页再简单不过——直接把SVG代码粘进去即可。它和网页完美融合,文字还能被搜索引擎收录、被用户选中复制。
如果要放到Word文档或者PPT里,我一般会先把SVG转成PNG。方法有三种:第一种是用浏览器打开HTML文件,右键SVG区域选择“图片另存为”,得到的就是矢量兼容格式;第二种是用开发工具截图,将浏览器窗口设成2倍缩放(device scale factor=2)再截,得到的PNG更清晰;第三种是写一个批量转换脚本,用sharp或puppeteer在Node环境里把SVG渲染成任意分辨率的PNG。
有一点必须提醒:如果你的报告要打印,或者有高分辨率LED屏幕展示需求,尽量用SVG源文件或者PDF格式,不要用PNG。PNG放大到原图两倍以上,边缘发虚的问题就出来了,这违背了“出版级”的初衷。
5. 我踩过的坑:常见问题与排查技巧实录
5.1 文字发虚、边缘模糊的问题
第一次用SVG画架构图时,我把图嵌进网页,结果在部分Windows电脑上文字发虚,和macOS上的效果差一大截。排查下来发现了两个原因。
第一是字体渲染差异。Windows上如果没有安装中文字体栈里的字体,会回退到一种默认字体,小字号下渲染不够锐利。解决方法是完善字体栈,把“Microsoft YaHei”放在中文字体前面,必要时嵌入Web字体。第二是SVG被CSS做得过小,然后被浏览器强行放大,这时文字边缘会模糊。解决方法是确保SVG的实际渲染尺寸不低于设计尺寸,或者用viewBox配合响应式容器时,留出足够安全边距。
5.2 viewBox 和实际长宽比不一致导致变形
这个坑特别隐蔽。我在给一个客户做架构图时,viewBox设置成0 0 1200 900,但是外层容器的CSS宽度是1200、高度却是800,结果整个图被垂直压扁。原因在于SVG默认会拉伸去适配容器宽高比。
解决方案有三个:一是让容器宽高比和viewBox一致;二是给svg设置preserveAspectRatio="xMidYMid meet",这样它会保持纵横比并在容器里居中,多出的区域留白;三是用preserveAspectRatio="xMidYMid slice",让图铺满容器但会裁剪两侧。做架构图推荐第一种或第二种,视觉上更可控。
5.3 节点数量增多后页面明显卡顿
SVG的DOM节点是“有代价的”,一个大型架构图动辄几百个节点和连线,每个节点还有阴影filter,页面帧率会明显下降。我测试过一次包含400个节点的图,在普通笔记本上滚动时已经能感到迟滞。
优化策略一般有几个方向:合并路径和图形,使用CSS的will-change;减少filter的使用,因为阴影滤镜计算开销很大,能用伪影层模拟就不用filter;将大图拆成多个SVG按需渲染;如果是动态数据,对频繁更新的元素分组,避免全量diff。diagram-design源码里对静态图做了一版优化,把所有静态节点合并成单个<g>,配合静态渲染缓存,实际性能提升很可观。
5.4 常见问题速查表
| 问题 | 根因 | 快速处理方案 |
|---|---|---|
| 文字模糊 | 字体缺失或SVG被缩放 | 完善字体栈,保持渲染尺寸接近设计尺寸 |
| 图被拉伸变形 | viewBox与容器比例不一致 | 设置preserveAspectRatio或统一宽高比 |
| 节点阴影不显示/渲染异常 | filter在部分浏览器兼容性差异 | 使用基础filter,避免过多复杂滤镜 |
| 节点数量多页面卡顿 | DOM节点多、filter开销大 | 合并静态分组,减少阴影filter,分批渲染 |
| 高DPI导出模糊 | 直接截图分辨率不够 | 用2x缩放截图或用脚本渲染PNG |
| SVG在不同浏览器颜色有差异 | 颜色空间与渲染引擎差异 | 确认图片嵌入方式,必要时用统一的sRGB |
这张表是我在实际使用项目过程中总结出来的,也结合了团队成员反馈的真实案例。每一条背后都对应过一个具体的线上事故,按时排查能省下不少时间。
6. 评测总结与一点扩展思路
如果你只把这个项目当成“画图工具”,它可能不如Polka、Excalidraw这些来得快。但如果你需要一套稳定、可编程、能进代码评审、能统一团队视觉规范的图解方案,它几乎是目前最值得参考的开源答案。设计上的克制感、代码里的工程化细节、对“审美参数”的封装,让它不只是好看而已。
就我个人经验来说,这类基于SVG的方案特别适合三个场景:一是技术架构文档的自动化生成,二是团队内部的知识库配图规范化,三是产品汇报中需要高完成度可视化的场景。你可以把它当成一个基础规范,再往上叠加自动布局算法、数据驱动渲染、实时协作能力,想象空间很大。
还有一个可以立刻上手的思路:把你目前最常用的架构图重新用HTML+SVG画一遍。不需要一上来就追求复杂,先把几个核心节点和连线的主题统一好,用CSS变量把配色和字体定下来,再逐步添加细节。画完对比一下,你会明显感觉到“专业感”这件事,其实是用规范堆出来的。