AI + Excalidraw 自然语言绘图技术分析
一、概述
1. 项目背景
A. 核心问题
技术文档创作过程中,绘制流程图、时序图、架构图等手绘风格图表往往需要手动操作绘图工具,耗时且不直观。
B. 解决方案
结合 Excalidraw 开源手绘风格白板与大语言模型,实现通过自然语言描述自动生成手绘风格图表的工具。
2. 技术亮点
A. 流式渲染
AI 生成 JSON 元素后实时解析并渲染到画布,边生成边画图。
B. 多端适配
支持桌面端和移动端布局,移动端采用上下布局设计。
C. 数据隐私
所有画布数据和对话历史保存在浏览器 localStorage,不上传服务器。
3. 技术栈
- 前端:Next.js + @excalidraw/excalidraw
- 后端:Vercel AI SDK
- AI 服务:支持 OpenAI、智谱、阿里百炼等兼容接口
二、系统架构
1. 整体架构
graph TD
A[用户输入描述] --> B[AI 服务端]
B --> C[流式生成 Excalidraw JSON]
C --> D[前端流式解析器]
D --> E[Excalidraw 画布渲染]
F[localStorage] --> D
F --> E2. 组件交互
sequenceDiagram
participant U as 用户
participant F as 前端界面
participant A as AI 服务
participant E as Excalidraw 画布
participant L as localStorage
U->>F: 输入绘图描述
F->>A: 发送对话请求
A-->>F: 流式返回 JSON 元素
F->>F: 实时解析 JSON
loop 每解析一个元素
F->>E: 添加元素到画布
E-->>U: 实时渲染更新
end
F->>L: 保存对话历史和画布数据三、核心技术实现
1. Excalidraw JSON 规范
A. 元素类型
Excalidraw 通过 JSON 描述图形元素,支持以下类型:
| 类型 | 说明 | 特有属性 |
|---|---|---|
| rectangle | 矩形 | - |
| ellipse | 椭圆 | - |
| diamond | 菱形 | - |
| text | 文本 | text, fontSize, fontFamily |
| arrow | 箭头 | points, endArrowhead |
| line | 线条 | points |
B. 基础元素结构
每个元素包含以下基础属性:
- id:元素唯一标识
- type:元素类型
- x, y:位置坐标
- width, height:尺寸
- backgroundColor:填充颜色
- strokeColor:边框颜色
C. 元素示例
{
"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"
}
]
}2. AI 提示词设计
A. 输出格式要求
- 先简要说明要画什么,然后连续输出所有 JSON 元素
- 禁止在 JSON 元素之间穿插说明文字
- 每个元素直接输出纯 JSON 对象
- 禁止使用代码块标记(避免反引号)
- 必须使用标准 JSON 格式
B. 文字处理规则
- 中英文宽度计算
- 形状内文字双向绑定
- fontSize 和 fontFamily 设置
C. 箭头规范
- points 使用相对坐标写法
- 支持各方向箭头
- endArrowhead 箭头样式设置
D. 颜色规范
使用 Excalidraw 内置调色板,确保颜色一致性。
3. 流式 JSON 解析
A. 核心挑战
AI 返回流式内容,需要:
- 追踪花括号深度处理嵌套 JSON
- 正确处理字符串内的花括号
- 记录已处理位置避免重复解析
B. 解析算法
function extractJsonObjects(text) {
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++) {
const char = text[j];
// 处理转义字符
if (char === '\\' && j + 1 < text.length) {
j++;
continue;
}
// 处理字符串边界
if (char === '"') {
inString = !inString;
continue;
}
// 在字符串内不计算花括号
if (inString) continue;
if (char === '{') depth++;
else if (char === '}') {
depth--;
if (depth === 0) {
// 找到完整的 JSON 对象
results.push(text.slice(startIndex, j + 1));
i = j + 1;
break;
}
}
}
}
return results;
}4. 实时渲染
A. 元素添加流程
通过 Excalidraw API 的 updateScene 方法将解析的元素添加到画布:
useImperativeHandle(ref, () => ({
addElements: (newElements) => {
const api = excalidrawAPIRef.current;
const currentElements = api.getSceneElements();
// 处理 id 冲突
const existingIds = new Set(currentElements.map(el => el.id));
const elementsToAdd = newElements.map(el => {
if (existingIds.has(el.id)) {
return { ...el, id: generateNewId() };
}
return el;
});
// 更新画布
api.updateScene({
elements: [...currentElements, ...elementsToAdd],
});
},
}));B. ID 冲突处理
- 检查现有元素的 ID
- 发现冲突时生成新 ID
- 确保每个元素唯一标识
5. 元素默认值补全
A. 降级策略
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,
};
}B. 字段说明
- roughness:控制手绘效果的粗糙程度
- seed:随机种子,产生自然的手绘变化
- opacity:透明度设置
- groupIds:元素分组支持
四、后端服务设计
1. AI 服务兼容层
A. 多服务支持
封装统一的 AI 服务接口,支持:
- OpenAI
- 智谱 AI
- 阿里百炼
- 其他 OpenAI 兼容服务
B. 调用方式
使用 Vercel AI SDK 对接大模型,实现流式响应。
2. 安全设计
A. API 密钥保护
- AI 调用在服务端进行
- 不向客户端暴露 API 密钥
B. 日志记录
记录每次对话的信息:
- IP 地址
- User-Agent
- 对话内容
- 响应时间
五、前端功能设计
1. 数据持久化
A. localStorage 存储
- 对话历史保存在 localStorage
- 画布数据保存在 localStorage
- 刷新页面不丢失数据
B. 隐私保护
- 所有数据仅存储在浏览器本地
- 不上传到服务器
- 用户完全控制自己的数据
2. 移动端适配
A. 布局设计
- 桌面端:左右布局
- 移动端:上下布局(画布在上方,输入框在底部)
B. 功能限制
移动端核心功能:
- AI 生成图表
- 查看渲染效果
- 基础画布操作
六、实现方式对比
1. AI 辅助实现
A. 适用场景
- 已清楚实现思路
- 需要快速原型
- 减少重复劳动
B. 操作方式
将详细需求整理为 prompt,使用 AI IDE 的 Plan 模式生成代码。
C. 优缺点
优点:
- 开发速度快
- 核心逻辑可靠
缺点:
- 对实现细节了解不深
- 可能需要调整代码
2. 手动实现
A. 适用场景
- 学习技术思路
- 理解实现细节
- 掌握核心技术
B. 学习价值
- 深入理解流式解析
- 掌握 Excalidraw API
- 熟悉 AI 集成方案
七、技术评估
1. 当前状态
A. 技术可行性
流程已打通,核心功能可用。
B. 实际效果
作者评价:流程是通的,效果是拉胯的。
C. 应用定位
目前仅适合作为玩具体验,距离生产可用还有差距。
2. 技术挑战
A. AI 生成质量
- JSON 格式准确性
- 元素布局合理性
- 箭头连接准确性
B. 复杂图表支持
- 大规模元素渲染
- 元素关系自动布局
- 美观性优化
3. 改进方向
A. 提示词优化
- 更精确的格式约束
- 更好的布局指导
- 更丰富的示例
B. 后处理增强
- 自动布局算法
- 元素对齐优化
- 美观度调整
C. 多轮对话
- 支持修改已有图表
- 增量添加元素
- 智能调整布局
八、相关资源
1. 官方文档
- Excalidraw 集成文档:https://docs.excalidraw.com/docs/@excalidraw/excalidraw/integration
- GitHub 仓库:113k+ star
2. 技术栈
- Next.js:React 框架
- @excalidraw/excalidraw:Excalidraw 官方包
- Vercel AI SDK:AI 集成工具
3. 在线体验
- 工具地址:https://www.lzkz.top/tool/excalidraw
- 作者:松柏