AI+Excalidraw自然语言手绘技术图测评
✨前言
手绘风格的流程图、架构图,在技术文档和分享中总是别具一格。Excalidraw 这个开源白板工具,GitHub 上已经积累了 113k star,画出来的东西自带手绘质感,挺有辨识度。
最近琢磨了一下它的原理——发现 Excalidraw 其实是通过 JSON 来定义图形的。顺着这个思路,一个想法冒了出来:能不能让 AI 直接生成这些 JSON,从而实现全自动绘图?于是做了个小工具,把 AI 和 Excalidraw 串起来,流式输出、实时渲染,边生成边画图。
下面这张动图虽然压缩得有点糊,但能看出是流式渲染的效果:
移动端同样可以运行:
体验地址放在文末。直接进入正题。
AI 实现
有两种路子可以走。一种是完全交给 AI,你只负责说清楚需求,然后当个监工——这也是现在做新功能最省力的方式;另一种就是手动编码,一步一步来,更适合学习原理。
先说第一种。只需要把需求整理成一段清晰的 prompt,丢给 AI 就行了:
帮我实现一个 AI + Excalidraw 手绘风格绘图工具,具体要求如下:
## 一、功能需求
1. 集成 Excalidraw 画板,参考官方文档:https://docs.excalidraw.com/docs/@excalidraw/excalidraw/integration
2. 通过 AI 对话生成 Excalidraw JSON 格式的图形元素
3. 流式输出 + 实时渲染:每解析到一个完整的 JSON 元素就立即渲染到画布
4. 支持移动端和桌面端布局
## 二、后端要求
1. AI 调用在服务端进行,不暴露 API 密钥
2. 记录每次对话的 IP、User-Agent、对话内容、响应时间等信息
3. 支持灵活切换各家 AI 服务(OpenAI、智谱、阿里百炼等),封装统一的兼容层
## 三、前端要求
1. 对话历史保存在 localStorage,不依赖后端加载
2. 画布数据也保存在 localStorage,刷新不丢失
3. 流式解析 AI 返回的 JSON 元素,处理嵌套和字符串内的花括号
4. 为 AI 生成的元素补全 Excalidraw 必需的默认字段
## 四、代码质量
1. 组件封装:AI 服务层、流式解析器、画布组件、对话组件分离
2. 类型安全:使用 TypeScript,定义完整的类型
3. 可复用:AI 服务封装成可配置的模块
## 五、AI 绘图提示词要点
需要设计一个 System Prompt,包含:
- 输出格式:纯 JSON,禁止代码块,方便流式解析
- 文字处理:中英文宽度计算、形状内文字双向绑定
- 箭头规范:points 相对坐标写法
- 常用颜色:Excalidraw 内置调色板
最好用 AI IDE 的 Plan 模式(比如 Cursor、Trae),先规划,再执行。AI 生成的代码可能需要微调,但核心逻辑基本靠谱。这种方式的好处就是快——原本三小时的活,三分钟就能搞定;缺点是对具体实现细节的掌握会弱一些。
手动实现
如果想扎实理解背后的原理,更推荐自己手动写一遍。
整体架构
整个工具的架构分为三层:
[用户输入描述]
↓
[AI 流式生成 Excalidraw JSON]
↓
[流式解析 JSON 元素]
↓
[实时渲染到 Excalidraw 画布]
核心逻辑很简单:用户描述想画什么 → AI 生成符合 Excalidraw 规范的 JSON 元素 → 前端实时解析并渲染。
前端这边用 Next.js 搭建,集成了官方的 @excalidraw/excalidraw 包。后端使用 Vercel AI SDK 对接大模型,支持 OpenAI 以及兼容的服务(智谱、阿里百炼等)。
核心实现
一、Excalidraw JSON 规范
Excalidraw 绘图的核心是 JSON。每个元素都有 id、type、x、y、width、height 这些基础属性,不同类型的元素还有特定字段。
支持的元素类型:
| 类型 | 说明 | 特有属性 |
|---|---|---|
rectangle | 矩形 | - |
ellipse | 椭圆 | - |
diamond | 菱形 | - |
text | 文本 | text, fontSize, fontFamily |
arrow | 箭头 | points, endArrowhead |
line | 线条 | points |
一个简单的矩形元素示例:
{
"type": "excalidraw",
"version": 2,
"source": "https://excalidraw.com",
"elements": [
{
"id": "rect-1",
"type": "rectangle",
"x": 100,
"y": 100,
"width": 150,
"height": 80,
"backgroundColor": "#a5d8ff",
"strokeColor": "#1971c2"
}
]
}
其中 backgroundColor 是填充色,strokeColor 是边框颜色。
二、AI 提示词设计
为了让 AI 生成正确的 JSON 并且保证出图效果,需要在提示词里提供必要的规则:
- 输出格式:纯 JSON,不要代码块(方便流式解析)
- 文字处理:中英文宽度计算规则,形状内文字双向绑定
- 箭头规范:
points是相对坐标,各方向箭头的写法 - 常用颜色:Excalidraw 内置调色板
一个参考 prompt 框架是这样的:
你是一个专业的 Excalidraw 绘图助手。用户会描述他们想要绘制的图形、流程图、架构图等,你需要生成对应的 Excalidraw 元素 JSON。
## 输出格式要求
1. **先说明,后输出**:先简要说明要画什么,然后连续输出所有 JSON 元素
2. **禁止**在 JSON 元素之间穿插说明文字
3. 每个元素直接输出纯 JSON 对象,以 { 开头,以 } 结尾
4. **禁止**使用代码块(禁止 ``` 符号)
5. **必须**使用标准 JSON 格式:键值对用冒号分隔(如 "x":100),不要写成等号
## 文字处理
## 箭头和线条
## 元素基础结构
## 基础形状
## 常用颜色
因为具体内容太长,这里就不展开了。需要的同学可以自己找完整版本。
三、流式 JSON 解析
AI 返回的内容是流式的,需要边接收边解析。核心解析逻辑:
// 从流式文本中提取完整的 JSON 对象
function extractJsonObjects(text: string) {
const results = []
let i = 0
while (i < text.length) {
const startIndex = text.indexOf('{', i)
if (startIndex === -1) break
// 追踪花括号深度,处理嵌套
let depth = 0
let inString = false
for (let j = startIndex; j < text.length; j++) {
// ... 处理转义字符和字符串
if (char === '{') depth++
else if (char === '}') {
depth--
if (depth === 0) {
// 找到完整的 JSON 对象
results.push(text.slice(startIndex, j + 1))
break
}
}
}
}
return results
}
这里有三个关键点:
- 追踪花括号深度来处理嵌套 JSON
- 正确处理字符串内的花括号(避免误判)
- 记录已处理位置,避免重复解析
当然,实际中可能还会遇到其他边界情况,按需处理就好。
四、实时渲染
解析出元素后,通过 Excalidraw API 添加到画布:
// 暴露给父组件的方法
useImperativeHandle(ref, () => ({
addElements: (newElements) => {
const api = excalidrawAPIRef.current
const currentElements = api.getSceneElements()
// 处理 id 冲突
const elementsToAdd = newElements.map(el => {
if (existingIds.has(el.id)) {
return { ...el, id: generateNewId() }
}
return el
})
// 更新画布
api.updateScene({
elements: [...currentElements, ...elementsToAdd],
})
},
}))
到这里核心流程就跑通了。不过为了稳定性,还有个重要的补充步骤。
五、元素默认值补全
AI 通常只生成必要字段,需要补全 Excalidraw 要求的其他字段,作为一种降级策略:
function getDefaultElementProps() {
return {
angle: 0,
strokeColor: '#1e1e1e',
backgroundColor: 'transparent',
fillStyle: 'solid',
strokeWidth: 2,
roughness: 1, // 手绘粗糙度
opacity: 100,
seed: Math.random() * 100000, // 随机种子,产生手绘效果
version: 1,
versionNonce: Math.random() * 1000000000,
isDeleted: false,
groupIds: [],
boundElements: null,
}
}
移动端适配
为了让手机也能用,做了移动端的适配。核心需求是能通过 AI 生成图形并看到效果,编辑之类的操作在手机上就不奢求了。移动端采用上下布局:上面是画布,底部是输入框。
数据持久化
所有画布数据都保存在 localStorage 里,不会上传到服务器,可以放心使用。
?结语
以上就是 AI + Excalidraw 实现手绘风格绘图工具的完整思路。核心就是让 AI 生成符合规范的 JSON,然后流式解析、实时渲染。
至于实际效果——可以总结为“流程是通的,效果是拉胯的”。目前这个阶段更适合作为小玩具玩玩,离生产级还有距离。感兴趣的话可以到 https://www.lzkz.top/tool/excalidraw 直接体验。




