Figma到代码的自动化工作流
原创
灵阙教研团队
B 基础 进阶 |
约 10 分钟阅读
更新于 2026-02-28 AI 导读
Figma到代码的自动化工作流 Figma 插件、Design-to-Code 工具与 Stitch 集成 1. 设计到代码的鸿沟 设计师在 Figma 中精心打磨的界面,到了开发者手中往往"走样"。这种鸿沟源于三个层面的信息损失: 设计意图 代码实现 +------------------+ +------------------+ | 间距: 16px | -----> | margin:...
Figma到代码的自动化工作流
Figma 插件、Design-to-Code 工具与 Stitch 集成
1. 设计到代码的鸿沟
设计师在 Figma 中精心打磨的界面,到了开发者手中往往"走样"。这种鸿沟源于三个层面的信息损失:
设计意图 代码实现
+------------------+ +------------------+
| 间距: 16px | -----> | margin: 15px | (数值偏差)
| 颜色: #3B82F6 | -----> | color: #3a81f5 | (取色误差)
| 字重: Medium | -----> | font-weight: 500 | (还好)
| 圆角: 12px | -----> | border-radius: 8px| (忽略)
| 动效: 300ms ease | -----> | (未实现) | (遗漏)
+------------------+ +------------------+
1.1 信息损失的三个层面
| 层面 | 损失类型 | 典型症状 |
|---|---|---|
| 令牌层 | 设计值未编码为变量 | 开发者硬编码随机值 |
| 组件层 | 组件变体/状态不完整 | 开发者漏实现某些状态 |
| 交互层 | 动效/手势未文档化 | 界面"能用但不灵动" |
1.2 自动化的目标
理想工作流:
Figma 设计
|
v
自动提取 (Token + 组件 + 交互)
|
v
代码生成 (框架组件 + 样式 + 动画)
|
v
人工精调 (业务逻辑 + 数据绑定)
|
v
发布
2. Figma 插件生态
2.1 核心工具链
| 工具 | 功能 | 定位 |
|---|---|---|
| Figma Tokens Studio | Design Token 管理 | Token 层 |
| Figma Dev Mode | 开发者视图/标注 | 交接层 |
| Figma REST API | 程序化访问设计文件 | 自动化基础 |
| Anima | Figma 转 React/Vue/HTML | 组件层 |
| Locofy | Figma 转 Next.js/React | 组件层 |
| Builder.io (Figma) | Figma 转任意框架 | 组件层 |
| Relay (Google) | Figma 转 Jetpack Compose | 移动端 |
2.2 Figma Tokens Studio 工作流
在 Figma 中:
+----------------------------------+
| Tokens Studio 插件面板 |
| |
| 颜色: |
| primary: #3B82F6 |
| secondary: #7C3AED |
| |
| 字体: |
| heading: 24px / 700 |
| body: 16px / 400 |
| |
| 间距: |
| sm: 8px |
| md: 16px |
| lg: 24px |
| |
| [同步到 GitHub] |
+----------------------------------+
|
v (Push to GitHub)
tokens.json (Git Repository)
|
v (CI: Style Dictionary)
CSS / Tailwind / TS
配置同步到 GitHub:
{
"name": "design-tokens",
"tokenSets": ["global", "light", "dark"],
"storage": {
"provider": "github",
"repository": "org/design-system",
"branch": "main",
"filePath": "tokens"
},
"transformers": [
{
"platform": "css",
"output": "dist/tokens.css"
},
{
"platform": "tailwind",
"output": "dist/tailwind.config.js"
}
]
}
3. Figma REST API 自动化
3.1 API 概览
Figma API 端点:
GET /v1/files/:file_key # 获取文件结构
GET /v1/files/:file_key/nodes?ids=:ids # 获取特定节点
GET /v1/images/:file_key?ids=:ids # 导出图片
GET /v1/files/:file_key/styles # 获取样式
GET /v1/files/:file_key/components # 获取组件
3.2 自动提取设计数据
import requests
FIGMA_TOKEN = "figd_..."
FILE_KEY = "abcdef123"
headers = {"X-Figma-Token": FIGMA_TOKEN}
def get_figma_file(file_key):
"""获取 Figma 文件完整结构"""
url = f"https://api.figma.com/v1/files/{file_key}"
response = requests.get(url, headers=headers)
return response.json()
def extract_colors(file_data):
"""从 Figma 文件提取颜色样式"""
colors = {}
styles = file_data.get("styles", {})
for style_id, style_info in styles.items():
if style_info["styleType"] == "FILL":
# 获取样式节点详情
node = get_node(FILE_KEY, style_id)
fills = node.get("fills", [])
if fills and fills[0]["type"] == "SOLID":
color = fills[0]["color"]
hex_color = rgb_to_hex(color["r"], color["g"], color["b"])
colors[style_info["name"]] = hex_color
return colors
def extract_typography(file_data):
"""从 Figma 文件提取字体样式"""
typography = {}
styles = file_data.get("styles", {})
for style_id, style_info in styles.items():
if style_info["styleType"] == "TEXT":
node = get_node(FILE_KEY, style_id)
style = node.get("style", {})
typography[style_info["name"]] = {
"fontFamily": style.get("fontFamily"),
"fontSize": style.get("fontSize"),
"fontWeight": style.get("fontWeight"),
"lineHeightPx": style.get("lineHeightPx"),
"letterSpacing": style.get("letterSpacing"),
}
return typography
def export_component_images(file_key, component_ids, scale=2):
"""导出组件为图片"""
ids = ",".join(component_ids)
url = f"https://api.figma.com/v1/images/{file_key}"
params = {"ids": ids, "scale": scale, "format": "png"}
response = requests.get(url, headers=headers, params=params)
return response.json()["images"]
3.3 自动化管线
GitHub Actions Workflow:
+-------------------+ +-------------------+
| Figma Webhook | --> | GitHub Actions |
| (设计文件更新) | | (自动触发) |
+-------------------+ +-------------------+
|
+---------------+---------------+
| | |
v v v
提取 Tokens 导出组件图片 生成代码
(API + 转换) (PNG/SVG) (模板引擎)
| | |
v v v
tokens.css assets/ components/
tailwind.config icons/ Button.tsx
Card.tsx
| | |
+---------------+---------------+
|
v
Pull Request
(自动 review)
4. Design-to-Code 工具
4.1 Anima
Anima 将 Figma 设计转换为 React/Vue/HTML 代码。
工作流程:
1. 在 Figma 中安装 Anima 插件
2. 选择要导出的 Frame
3. Anima 分析层级结构
4. 生成组件代码 (React / Vue / HTML)
5. 在 Anima Web 平台预览
6. 下载或通过 CLI 集成到项目
输出质量:
- 布局: Flexbox/Grid (80% 准确)
- 样式: CSS / Tailwind (90% 准确)
- 响应式: 需手动调整断点
- 交互: 基础状态变化 (hover/active)
- 业务逻辑: 需完全手动添加
4.2 Locofy
Locofy 专注于生成 Next.js / React 项目级代码。
Locofy 特性:
- 自动识别组件边界
- 生成路由结构 (Next.js App Router)
- 输出 Tailwind CSS 类
- 支持自定义组件映射
- 集成 Storybook
局限:
- 复杂动画不支持
- 需要 Figma 设计遵循特定规范
- 生成代码需要大量重构
4.3 Builder.io Figma 插件
Builder.io 方案:
Figma -> Visual Editor -> React / Vue / Svelte / Angular / etc.
优势:
- 支持几乎所有前端框架
- 可视化编辑器作为中间层
- 支持 A/B 测试
- CMS 内容绑定
用法:
1. Figma 中选择设计
2. "Import to Builder" 一键导入
3. 在 Builder 编辑器中调整
4. 生成目标框架代码
5. Google Stitch 集成
5.1 Stitch 在工作流中的定位
传统流程:
需求 -> Figma 设计 (3-5天) -> 开发 (5-10天)
Stitch 加速流程:
需求 -> Stitch 生成原型 (5分钟) -> 评审 -> 代码转换 -> 开发精调 (3-5天)
5.2 Stitch MCP 工作流
// 使用 Stitch MCP 工具链
// 1. 列出项目
const projects = await stitch.listProjects();
// 2. 获取项目详情
const project = await stitch.getProject({ projectId: "abc123" });
// 3. 列出屏幕
const screens = await stitch.listScreens({ projectId: "abc123" });
// 4. 获取屏幕详情(HTML + CSS)
const screen = await stitch.getScreen({
projectId: "abc123",
screenId: "screen_1"
});
// 5. 转换为框架代码
function convertStitchToReact(html, css) {
// 解析 HTML 结构
// 将 Tailwind CDN 类转为本地 Tailwind
// 替换静态图片为 next/image
// 提取可复用组件
// 绑定 props 和事件
}
5.3 DESIGN.md 工作流
# DESIGN.md - 语义设计系统
## Colors
- primary: #2563EB (蓝色, 主操作/链接)
- secondary: #7C3AED (紫色, AI 元素)
- surface: #FFFFFF (浅色模式背景)
- text-primary: #1E293B (主文字)
## Typography
- heading: Inter 700 (24/32/40px)
- body: Inter 400 (16px, line-height 1.6)
- code: JetBrains Mono 400 (14px)
## Spacing
- base: 8px
- content-gap: 16px
- section-gap: 32px
- page-margin: 48px
## Components
- card: radius-12, shadow-sm, padding-24
- button-primary: bg-primary, text-white, radius-8, h-40
- input: border-gray-200, radius-8, h-40, focus:ring-primary
Stitch 在后续屏幕生成时引用 DESIGN.md 保持一致性。
6. 代码转换管线
6.1 HTML 到 React 转换
// 转换规则
const conversionRules = {
// HTML 属性到 JSX
attributeMap: {
'class': 'className',
'for': 'htmlFor',
'tabindex': 'tabIndex',
'onclick': 'onClick',
'onchange': 'onChange',
},
// 自闭合标签
selfClosing: ['img', 'br', 'hr', 'input'],
// style 字符串到对象
convertInlineStyle(styleStr: string): Record<string, string> {
return Object.fromEntries(
styleStr.split(';')
.filter(Boolean)
.map(s => {
const [key, value] = s.split(':').map(p => p.trim());
const camelKey = key.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
return [camelKey, value];
})
);
},
// Tailwind CDN 到本地
migrateTailwindCDN(html: string): string {
// 移除 CDN script 标签
// 保留 class 中的 Tailwind 类名
// 确保 tailwind.config.js 包含所有使用的类
return html.replace(
/<script src="https:\/\/cdn\.tailwindcss\.com"><\/script>/,
''
);
}
};
6.2 图片资源处理
async function processImages(html: string, outputDir: string) {
const imgRegex = /<img[^>]+src="([^"]+)"[^>]*>/g;
let match;
while ((match = imgRegex.exec(html)) !== null) {
const src = match[1];
if (src.startsWith('http')) {
// 下载远程图片
const filename = generateFilename(src);
await downloadImage(src, path.join(outputDir, 'public/images', filename));
// 替换为 next/image
html = html.replace(
match[0],
`<Image src="/images/${filename}" alt="" width={800} height={600} />`
);
} else if (src.startsWith('data:')) {
// Base64 图片保存为文件
const filename = `image_${Date.now()}.png`;
await saveBase64Image(src, path.join(outputDir, 'public/images', filename));
html = html.replace(
match[0],
`<Image src="/images/${filename}" alt="" width={800} height={600} />`
);
}
}
return html;
}
7. 组件提取策略
7.1 何时提取组件
提取信号:
1. 重复出现 2+ 次的相同结构
2. 具有明确边界的独立功能块
3. 存在变体(不同尺寸/颜色/状态)
4. 未来可能复用
不提取信号:
1. 只出现一次且不太可能复用
2. 结构过于简单(单个元素)
3. 提取后 props 比原始代码还复杂
7.2 提取流程
原始 HTML:
<div class="flex items-center gap-3 p-4 rounded-lg border">
<img class="w-10 h-10 rounded-full" src="avatar.jpg" alt="User" />
<div>
<p class="font-medium text-gray-900">张三</p>
<p class="text-sm text-gray-500">产品经理</p>
</div>
<button class="ml-auto text-blue-600">关注</button>
</div>
提取为组件:
// UserCard.tsx
interface UserCardProps {
name: string;
role: string;
avatarUrl: string;
onFollow?: () => void;
}
function UserCard({ name, role, avatarUrl, onFollow }: UserCardProps) {
return (
<div className="flex items-center gap-3 p-4 rounded-lg border">
<Image
src={avatarUrl}
alt={name}
width={40}
height={40}
className="rounded-full"
/>
<div>
<p className="font-medium text-text-primary">{name}</p>
<p className="text-sm text-text-secondary">{role}</p>
</div>
{onFollow && (
<button onClick={onFollow} className="ml-auto text-primary">
关注
</button>
)}
</div>
);
}
8. CI/CD 集成
8.1 设计变更自动同步
# .github/workflows/design-sync.yml
name: Design Token Sync
on:
push:
paths:
- 'tokens/**'
jobs:
build-tokens:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: npm ci
- name: Build tokens
run: npx style-dictionary build
- name: Run visual regression
run: npx chromatic --project-token=${{ secrets.CHROMATIC_TOKEN }}
- name: Check contrast ratios
run: node scripts/check-contrast.js
- name: Create PR if tokens changed
uses: peter-evans/create-pull-request@v5
with:
title: "chore: update design tokens"
body: "Automated token sync from Figma Tokens Studio"
branch: design-token-update
8.2 视觉回归检测
Chromatic 工作流:
1. Storybook 构建
2. 截图每个组件的每个变体
3. 与基准截图对比
4. 差异 > 阈值 -> 标记为需审核
5. 设计师/开发者审核差异
6. 接受 -> 更新基准 | 拒绝 -> 修复代码
9. 实际工作流对比
| 方案 | 自动化程度 | 代码质量 | 维护成本 | 适用场景 |
|---|---|---|---|---|
| 纯手写 | 0% | 最高 | 低 | 复杂交互组件 |
| Figma Dev Mode + 手写 | 20% | 高 | 低 | 日常开发 |
| Stitch -> 手动转换 | 40% | 中高 | 中 | 新页面快速原型 |
| Anima / Locofy | 60% | 中 | 高 | 市场营销页 |
| Token Studio + CI | 80% (令牌层) | 高 | 低 | 设计系统维护 |
10. 推荐工作流
最佳实践工作流:
1. 设计阶段:
Figma + Tokens Studio (管理 Token)
|
v
2. 原型验证:
Google Stitch (快速生成高保真原型)
|
v
3. Token 同步:
Tokens Studio -> GitHub -> Style Dictionary -> CSS/Tailwind
(自动化, CI/CD)
|
v
4. 组件开发:
手工编写 React/Vue 组件 (引用 Token)
Storybook 文档化
|
v
5. 质量保障:
Chromatic 视觉回归
axe-core 无障碍检测
|
v
6. 持续同步:
设计变更 -> Token 更新 -> 自动 PR -> 审核 -> 合并
核心理念:Token 自动化,组件手写。令牌层完全自动化同步,组件层由开发者手工编写以确保质量和可维护性,两者通过 Token 引用保持一致。
Maurice | maurice_wen@proton.me