Excalidraw 支持导入/导出 JSON 实现数据迁移
在远程协作日益成为常态的今天,团队对可视化工具的需求早已超越了“画图”本身。工程师、产品经理和设计师们需要一种既能快速表达想法,又能将这些想法持久化、版本化并嵌入工作流的工具。Excalidraw 正是在这一背景下脱颖而出——它以手绘风格降低创作门槛,同时通过一套简洁而强大的数据模型,让白板不再只是临时草稿,而是可编程、可追踪、可复用的设计资产。
这一切的核心,正是其对 JSON 格式的原生支持。无论是导出保存、跨平台迁移,还是与 AI 和自动化系统集成,JSON 成为了连接人与工具、创意与工程之间的桥梁。
数据如何被“记住”?解析 Excalidraw 的 JSON 结构
当你在 Excalidraw 中画下一个矩形或连上一条线时,你可能没意识到,这个动作背后其实是一次完整的状态序列化过程。整个画布不是一张图片,而是一个由对象组成的结构树,最终被封装成一个标准的 JSON 文档。
{ "type": "excalidraw", "version": 2, "source": "https://excalidraw.com", "elements": [ { "id": "A1", "type": "rectangle", "x": 100, "y": 100, "width": 200, "height": 100, "strokeColor": "#000000", "backgroundColor": "#ffff00", "fillStyle": "hachure" }, { "id": "L1", "type": "line", "points": [[0, 0], [50, -50]], "origin": [200, 150], "endBinding": { "elementId": "A1", "focus": 1 } } ], "appState": { "viewBackgroundColor": "#ffffff", "currentItemStrokeColor": "#000000", "gridSize": 20 } }这段 JSON 看似简单,实则承载了极其丰富的信息:
elements数组记录了所有图形元素,每个元素都有唯一的id,这是实现绑定、分组和增量更新的基础;- 坐标(
x,y)、尺寸、颜色等属性决定了视觉呈现; endBinding字段表明这条线是“粘”在某个形状上的,即使目标移动,连接关系依然保持;appState则保存了非图形状态,比如当前使用的笔刷颜色、是否开启网格、缩放比例等。
这意味着,当你把文件发给同事时,他看到的不只是图形,还包括你的视角位置、图层顺序甚至编辑偏好——就像完整地“复制”了一次你的工作台。
更重要的是,这种结构是人类可读、机器可操作的。你可以用文本编辑器打开.excalidraw文件,修改某个坐标的数值,再重新导入,就能看到图形位置发生变化。这为自动化打开了大门。
编程生成图表:从“手动绘制”到“代码驱动”
如果 JSON 只是用来备份和分享,那它的价值还停留在“静态文档”层面。真正让它变得强大的,是它可以被程序生成。
想象这样一个场景:你刚完成一次架构评审,会议纪要里写着“系统包含用户服务、订单服务和支付网关”。传统做法是会后手动打开白板工具,一个个拖拽框和连线去还原讨论结果。但在 Excalidraw 的世界里,这件事完全可以自动完成。
function createRectangleElement(id, x, y, width, height, color) { return { id: id, type: "rectangle", x: x, y: y, width: width, height: height, strokeColor: "#000000", backgroundColor: color, fillStyle: "solid", strokeWidth: 1, roughness: 1, opacity: 100, seed: Math.floor(Math.random() * 100000), version: 1, versionNonce: 0, updated: 1, isDeleted: false }; } // 示例:生成一个蓝色矩形 const rect = createRectangleElement("box1", 50, 50, 150, 80, "#add8e6"); // 构造完整文档 const excalidrawData = { type: "excalidraw", version: 2, source: "https://excalidraw.com", elements: [rect], appState: { viewBackgroundColor: "#ffffff" } }; console.log(JSON.stringify(excalidrawData, null, 2));上面这段脚本可以作为更大系统的组成部分。例如:
- 接入 LLM 模型,将自然语言描述解析为组件列表;
- 调用布局算法,自动排列微服务节点;
- 输出
.excalidraw文件,并嵌入 Confluence 页面或 GitHub README。
我在实际项目中就曾用类似方式,把 Terraform 的模块输出转化为网络拓扑图。每次基础设施变更后,CI 流水线自动生成最新的架构图并推送到知识库,彻底告别了“文档滞后”的尴尬。
而且由于 JSON 是纯文本,这类生成过程还能享受 Git 的完整版本控制。你可以清晰看到上周谁删了一个服务框,或者哪次合并引入了循环依赖。这正是“可视化即代码”的核心理念:图表不再是孤岛,而是系统的一部分。
多人协作背后的同步机制:为什么 JSON 如此关键?
虽然 Excalidraw 开源版默认不带服务器,但它的数据模型显然为协作做好了准备。多人实时编辑之所以可行,本质上是因为所有客户端都共享同一个“语言”——那就是 JSON 结构。
典型的协作流程如下:
- 用户 A 移动了一个组件;
- 客户端捕获变化,提取出该元素的新坐标和其他属性;
- 将变更打包成轻量级 JSON 片段(diff),通过 WebSocket 发送给服务端;
- 服务端广播给其他在线用户;
- 用户 B 的客户端收到消息后,根据
id找到对应元素,局部更新状态并重绘。
const socket = new WebSocket('wss://your-collab-server/ws'); scene.on('change', (elements) => { const updatePayload = { type: 'element-update', data: elements.map(e => ({ id: e.id, x: e.x, y: e.y, width: e.width, height: e.height })) }; socket.send(JSON.stringify(updatePayload)); }); socket.onmessage = (event) => { const msg = JSON.parse(event.data); if (msg.type === 'element-update') { msg.data.forEach(remoteEl => { const localEl = elements.find(e => e.id === remoteEl.id); if (localEl) { Object.assign(localEl, remoteEl); } }); reRenderScene(); } };这里的关键在于,每个元素都有唯一 ID,且状态字段明确。没有 ID,就无法匹配远端更新;字段不一致,则可能导致渲染错乱。而 JSON 提供了恰好够用的结构化能力,既不像 XML 那样冗长,也不像二进制格式那样不可读。
更进一步,一些高级部署会采用 CRDT(无冲突复制数据类型)来处理并发编辑。在这种模型下,每一个用户的本地操作都会生成一个带有逻辑时钟的 JSON 补丁,最终在不依赖中心协调者的情况下达成一致。这也是为什么 Excalidraw 即使在离线状态下仍能正常工作——因为它的设计哲学就是“先本地,后同步”。
当然,这也带来了一些注意事项:
- 不建议多人直接编辑同一个
.excalidraw文件并上传覆盖,容易造成冲突; - 若自行搭建后端,需补充权限控制和身份验证;
- 对于大型画布,应启用增量同步而非全量刷新,避免卡顿。
工程实践中的真实应用场景
场景一:AI 辅助绘图
越来越多团队开始尝试用大模型辅助系统设计。用户输入:“请画一个包含 Redis 缓存、MySQL 主从和负载均衡器的 Web 架构”,AI 就能返回对应的 JSON 结构。
我们曾开发过一个简单的中间层,接收 LLM 输出的 YAML 描述:
services: - name: nginx type: load_balancer position: [100, 100] - name: app-server type: server count: 3 connected_to: nginx然后通过模板引擎将其映射为符合 Excalidraw schema 的 JSON,用户下载后一键导入即可获得初稿。后续只需微调布局和样式,效率提升非常明显。
场景二:GitOps 式的图表管理
我们将所有重要的架构图以.excalidraw文件形式存入 Git 仓库,路径按业务域划分:
/docs/architecture/ ├── user-service.excalidraw ├── payment-flow.excalidraw └── deployment-topology.excalidrawPR 修改代码的同时,也可以附带更新图表。Code review 阶段, reviewers 可直接查看 JSON diff,判断是否有组件遗漏或连接错误。合并后,CI 自动将其渲染为 PNG 并发布到内部 Wiki。
这种方式的好处在于:
✅ 图表变更有迹可循
✅ 支持回滚到任意历史版本
✅ 新成员可通过 git log 快速理解演进过程
场景三:与知识库深度集成
Obsidian、Logseq 等双链笔记工具已成为技术团队的知识中枢。它们天然支持嵌入.excalidraw文件,且能在笔记中直接预览和编辑。
这意味着,你可以在一篇关于“登录流程优化”的笔记中,嵌入一张动态图解,点击即可进入编辑模式添加注释。而这张图的底层仍然是 JSON,依然可以被脚本扫描、分析甚至参与自动化测试。
比如我们曾写过一个检测脚本,遍历所有图表文件,查找是否存在未连接的孤立节点,提示用户清理废弃组件。这种“对图形进行代码审查”的能力,在传统图像格式下是完全无法实现的。
设计之外的考量:稳定性、安全与扩展
尽管 JSON 带来了极大的灵活性,但在实际使用中仍需注意几个关键点。
版本兼容性
Excalidraw 的 JSON schema 并非一成不变。随着新功能加入(如文本块支持 Markdown、新增箭头类型),字段结构可能会调整。旧版本可能无法正确解析新版导出的文件。
因此建议:
- 在团队内部统一使用相同版本的 Excalidraw;
- 或建立中间转换层,在导入前做 schema 迁移;
- 重要文档可同时保留 PNG 快照作为降级方案。
敏感信息泄露风险
别忘了,JSON 是明文的。如果你在图中标注了“数据库密码见 XXX 文档”或画出了内部 IP 段,这些内容都会随文件一起导出。
建议:
- 在对外分享前执行“脱敏导出”,过滤掉敏感文本和元数据;
- 使用插件自动扫描关键词并提醒;
- 企业环境可定制私有部署版本,限制导出权限。
性能边界
当画布元素超过千级时,单个 JSON 文件可能达到数 MB,加载和解析都会变慢。此时可考虑:
- 分片设计:将大图拆分为多个子图,通过链接跳转;
- 懒加载:仅在视口内渲染可见元素;
- 使用二进制压缩格式(如 CBOR)作为内部传输格式,仅在导出时转为 JSON。
结语:从绘图工具到认知基础设施
Excalidraw 的 JSON 导入/导出功能,表面上只是一个数据迁移特性,实则是其工程思想的集中体现:保持前端体验极简,同时为后端集成留足空间。
它没有强行内置复杂的协作服务器,而是通过开放的数据格式,把选择权交给用户。你可以把它当作一个本地草图工具,也可以基于它构建整套智能设计流水线。
更重要的是,它推动了一种新的工作范式——当我们能把“画一张图”变成“运行一段代码生成一个结构化文档”时,创造力就开始与自动化共舞。未来的系统设计,或许不再是某个人埋头苦画几小时,而是由 AI 生成初稿、团队共同迭代、CI 自动归档的闭环流程。
而 Excalidraw,正悄悄成为这场变革的基础设施之一。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考