开源了一个 AI-Native 的矢量设计工具,对标 Pencil.dev,让 AI Agent 直接画 UI
先说结论
我做了一个开源矢量设计工具叫 OpenPencil ,对标商业产品 Pencil.dev,核心差异点:
- 完全开源,MIT License,不是又一个套壳 SaaS
- AI-Native,不是"设计工具 + AI 插件",而是从架构层就为 AI 设计的
- Agentic Design,自带 MCP Server,Claude Code / Cursor / Windsurf 等 AI Agent 可以直接操作设计稿,不需要人打开 GUI
- Design-as-Code ,
.op文件就是结构化 JSON,能进 Git、能 diff、能 code review
如果你用过 Pencil.dev,你应该知道它的 AI 生成设计能力很强。但它是闭源的、付费的,而且设计稿锁在它的平台里。OpenPencil 想做的事情是------把同样的能力开源出来,同时让设计稿真正属于你的代码仓库。
GitHub 地址 → github.com/ZSeven-W/op...
为什么现在做这个有意义?
2025 年之后,AI 写代码已经不稀奇了。但你有没有发现一个断层------
AI 能帮你写出一个完整的后端服务,却画不好一个登录页面。
原因很简单:现有的设计工具(Figma、Sketch)都是为人类设计的。它们的文件格式是二进制或私有协议,API 有限,AI 想操作它们只能通过插件间接控制,效率极低。
而 Pencil.dev 看到了这个机会------它的 .pen 格式是结构化的,天然对 AI 友好。但问题是它是闭源商业产品。
OpenPencil 的思路是:如果设计稿本身就是一份 JSON,那 AI 读写设计稿就跟读写代码一样自然。 不需要插件,不需要 API 转换,直接操作数据结构。
这才是 AI 时代设计工具该有的样子。
Agentic Design:让 AI Agent 成为你的设计师
这是我最想展开讲的部分,也是 OpenPencil 和传统设计工具最大的区别。
什么是 Agentic Design?
简单说:设计稿不再只是人用鼠标拖出来的,AI Agent 可以自主读取、理解、修改、生成设计稿。
内置的 AI 设计生成
除了外部 Agent 调用,OpenPencil 自己也内置了 AI 设计生成。在编辑器的聊天面板里,你可以用自然语言描述需求:
"帮我设计一个 SaaS 定价页面,三个档位,支持年付/月付切换"
背后的架构是一个 Orchestrator + Sub-Agent 的编排系统:
空间分解:Header / Pricing Cards / Footer"] B --> C1["Sub-Agent 1"] B --> C2["Sub-Agent 2"] B --> C3["Sub-Agent 3"] C1 --> D["流式插入画布(带淡入动画)"] C2 --> D C3 --> D D --> E["Vision 校验
截图 → Vision API → 自动修复视觉问题"] style B fill:#6366f1,color:#fff style E fill:#f59e0b,color:#fff
几个关键设计决策:
- 空间分解而非语义分解:Orchestrator 按空间区域拆分任务,而不是按"标题、文案、按钮"拆分。因为设计本质上是空间排布问题,空间分解更符合直觉,子 Agent 之间的依赖也更少。
- 流式插入:节点不是生成完才一次性渲染,而是边生成边插入画布,用户可以实时看到 AI 在"画"。
- Vision 自校验 :生成完成后,自动截图发给 Vision API 检查,如果发现明显的视觉问题(文字溢出、对齐偏移、颜色对比度不够),自动修复。AI 不光会画,还会自己检查作业。
生成出来的不是图片,是真正的矢量节点树------每个元素都可以选中、编辑、调整属性、导出代码。
技术实现:React + Fabric.js 做设计工具有多难
下面聊点硬核的,给同样想做图形编辑器的同学一些参考。
最大的挑战:声明式 vs 命令式的双向同步
技术栈是 React 19 + Fabric.js v7 + Zustand v5。
React 是声明式的,Fabric.js 是命令式的。你用 Zustand store 管理数据,用 Fabric 渲染画布,两者之间的同步是整个项目最难的部分。
数据流架构:
工具栏 / 属性面板 / 图层面板"] -->|"Zustand hooks"| B["canvas-store
UI 状态:工具/选区/视口"] A -->|"Zustand hooks"| C["document-store
PenDocument · CRUD / 树操作"] B --> D["Fabric.js Canvas
命令式渲染"] C --> E["canvas-sync-lock
防止循环同步"] E -.->|"锁保护"| D style C fill:#6366f1,color:#fff style E fill:#f59e0b,color:#fff
核心原则:document-store 是唯一数据源,Fabric.js 只负责渲染。
但双向同步意味着:
- 用户在画布上拖对象 → Fabric 内部状态先变 → 事件回调写入 store
- 用户在面板改数值 → store 更新 → 需要同步到 Fabric 对象
A 更新 B,B 又更新 A,循环了。
解决方案是一个 canvas-sync-lock------谁在写入,就锁住另一方的监听。听起来简单,但批量操作、undo/redo、动画中间态、组内级联更新......每个场景的同步时序都不一样,调了很久。
Fabric.js v7 的坑
v7 把默认原点从 left/top 改成了 center/center。你写 left: 100, top: 100,对象中心点在 (100,100) 而不是左上角。
在做父子变换、自动布局、对齐吸附的时候,坐标系不统一会直接爆炸。解决方案就一行:
js
{ originX: 'left', originY: 'top' }
每个对象都显式声明,永远不信默认值。一行代码省了三天 debug。
另一个坑是默认 strokeWidth: 1,不要描边的时候必须显式设 strokeWidth: 0,否则你会看到每个对象都有一条若有若无的边框,排查起来很抓狂。
父子节点变换传播
Fabric.js 没有原生的父子层级,对象模型是扁平的。但设计工具里 Frame 嵌套子元素是基本操作。所以需要:
- document-store 维护树形结构
- 渲染时拍平成绝对坐标
- 操作时换算回相对坐标
- 父节点变换时手动传播给后代
缩放传播还好,旋转传播涉及三角函数和矩阵运算,单独抽了一个 parent-child-transform.ts 处理。
设计变量系统
支持设计变量(类似 CSS Custom Properties),关键决策:$variable 引用在 store 里原样保留,只在渲染时解析。
ts
// store 里存引用
{ fill: { color: '$color-primary' } }
// 渲染前解析为具体值
{ fill: { color: '#6366f1' } }
// 生成代码时输出 CSS 变量
{ fill: 'var(--color-primary)' }
好处:改变量值全局生效、多主题切换只需换变量集、代码生成零硬编码。支持多维度主题轴(Light/Dark × Compact/Comfortable = 4 种变体)。
完整技术栈
| 层级 | 技术 |
|---|---|
| 前端框架 | React 19 + TypeScript(严格模式) |
| 样式 | Tailwind CSS v4 + shadcn/ui |
| 画布引擎 | Fabric.js v7 |
| 状态管理 | Zustand v5 |
| 路由 | TanStack Start(文件路由) |
| 服务端 | Nitro |
| 桌面端 | Electron 35(macOS / Windows / Linux) |
| AI | Claude / OpenAI,Orchestrator + Sub-Agent 编排 |
| Agent 协议 | MCP Server(兼容 Claude Code / Cursor / Windsurf) |
| 运行时 | Bun |
最后
我做 OpenPencil 的初衷很简单:
2025 年了,AI 能写出整个应用的代码,却还是画不好一个 UI。 不是 AI 不够强,是现有的设计工具不给 AI 机会。文件格式是二进制的、API 是受限的、生态是封闭的。
Pencil.dev 证明了 AI-Native 设计工具这条路走得通,OpenPencil 想做的是把这条路开源出来------让每个开发者都能用上 Agentic Design,让设计稿真正成为代码仓库的一部分。
GitHub → github.com/ZSeven-W/op...
如果你对这些方向感兴趣,欢迎一起交流:
- Agentic Design --- AI Agent 自主操作设计稿的工作流
- Design-as-Code --- 设计稿版本管理、CI/CD、代码生成
- 图形编辑器开发 --- Canvas 2D / Fabric.js 踩坑经验
- AI 编排架构 --- Orchestrator + Sub-Agent 的任务分解
项目还在活跃开发中,欢迎 Star、欢迎 PR、欢迎 Issue。开源不易,你的每一颗 Star 都是继续做下去的动力。