一、现状说明
重要
- 手动截图 + AI识别(最简单,马上能用)
- Figma API + 自建MCP(需要开发,最灵活)
- Figma Inspect导出 + AI解析(折中方案)
二、方案1:手动截图 + AI识别(推荐新手)
这是最简单直接的方式,不需要任何配置。
Step 1: 准备设计稿
在Figma中打开你的设计稿,比如一个用户卡片组件。
假设设计稿长这样:
- 头像(圆形,64x64px)
- 用户名(16px,粗体,颜色#333)
- 职位(14px,常规,颜色#666)
- 在线状态指示器(绿色小圆点)
Step 2: 截图
按 Cmd/Ctrl + Shift + 4 截图,保存为 user-card.png
Step 3: 上传给AI
打开Claude,上传图片,然后输入:
这是一个用户卡片的设计稿,帮我生成React组件代码。
【要求】
1. 使用Ant Design
2. 使用CSS Modules写样式
3. 支持在线/离线状态
4. 组件要有TypeScript类型
请提取设计稿中的:
- 尺寸(宽高、间距、圆角)
- 颜色(文字色、背景色、边框色)
- 字体大小和粗细
- 布局方式
Step 4: AI分析并生成代码
AI会分析图片,输出:
UserCard.tsx
import { Avatar } from 'antd';
import styles from './UserCard.module.css';
interface UserCardProps {
user: {
id: string;
name: string;
position: string;
avatar: string;
isOnline: boolean;
};
onClick?: (userId: string) => void;
}
export default function UserCard({ user, onClick }: UserCardProps) {
return (
<div
className={styles.card}
onClick={() => onClick?.(user.id)}
>
<div className={styles.avatarWrapper}>
<Avatar size={64} src={user.avatar} />
{user.isOnline && <span className={styles.onlineBadge} />}
</div>
<div className={styles.info}>
<h3 className={styles.name}>{user.name}</h3>
<p className={styles.position}>{user.position}</p>
</div>
</div>
);
}
UserCard.module.css
.card {
width: 280px;
padding: 16px;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: box-shadow 0.3s;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
.avatarWrapper {
position: relative;
display: inline-block;
margin-bottom: 12px;
}
.onlineBadge {
position: absolute;
bottom: 2px;
right: 2px;
width: 12px;
height: 12px;
background: #52c41a;
border: 2px solid #fff;
border-radius: 50%;
}
.info {
text-align: center;
}
.name {
margin: 0 0 4px;
font-size: 16px;
font-weight: 600;
color: #333333;
}
.position {
margin: 0;
font-size: 14px;
color: #666666;
}
Step 5: 调整细节
如果AI生成的某个细节不对,比如间距不准确,直接告诉AI:
名字和职位之间的间距应该是8px,不是4px。还有卡片宽度应该是300px。
AI会立即修正代码。
三、方案2:Figma API + 自建MCP(进阶)
这个方案可以直接读取Figma文件数据,提取精确的设计token。
Step 1: 获取Figma Access Token
- 登录Figma
- 访问 https://www.figma.com/developers/api#access-tokens
- 点击 "Get personal access token"
- 生成token,保存好(只显示一次)
Step 2: 获取Figma File Key
打开你的Figma文件,URL类似这样:
https://www.figma.com/file/ABC123xyz/MyDesign
其中 ABC123xyz 就是File Key。
Step 3: 测试Figma API
用curl测试能否访问:
curl -H "X-Figma-Token: YOUR_TOKEN_HERE" \
https://api.figma.com/v1/files/ABC123xyz
如果返回JSON数据,说明成功。
Step 4: 创建Figma MCP Server
创建项目:
mkdir figma-mcp
cd figma-mcp
npm init -y
npm install @modelcontextprotocol/sdk axios
创建 server.js:
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import axios from 'axios'
const FIGMA_TOKEN = process.env.FIGMA_TOKEN
const server = new Server(
{
name: 'figma-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
)
server.setRequestHandler('tools/list', async () => {
return {
tools: [
{
name: 'read_figma_file',
description: '读取Figma文件内容',
inputSchema: {
type: 'object',
properties: {
fileKey: {
type: 'string',
description: 'Figma文件的Key(从URL获取)',
},
},
required: ['fileKey'],
},
},
{
name: 'get_component_styles',
description: '提取组件的样式信息',
inputSchema: {
type: 'object',
properties: {
fileKey: { type: 'string' },
nodeId: { type: 'string' },
},
required: ['fileKey', 'nodeId'],
},
},
],
}
})
server.setRequestHandler('tools/call', async (request) => {
const { name, arguments: args } = request.params
if (name === 'read_figma_file') {
const { fileKey } = args
try {
const response = await axios.get(
`https://api.figma.com/v1/files/${fileKey}`,
{
headers: { 'X-Figma-Token': FIGMA_TOKEN },
}
)
const file = response.data
// 提取关键信息
const summary = {
name: file.name,
pages: file.document.children.map((page) => ({
name: page.name,
components: extractComponents(page),
})),
}
return {
content: [
{
type: 'text',
text: JSON.stringify(summary, null, 2),
},
],
}
} catch (error) {
return {
content: [{ type: 'text', text: `错误: ${error.message}` }],
isError: true,
}
}
}
if (name === 'get_component_styles') {
const { fileKey, nodeId } = args
try {
const response = await axios.get(
`https://api.figma.com/v1/files/${fileKey}/nodes?ids=${nodeId}`,
{
headers: { 'X-Figma-Token': FIGMA_TOKEN },
}
)
const node = response.data.nodes[nodeId].document
const styles = extractStyles(node)
return {
content: [
{
type: 'text',
text: JSON.stringify(styles, null, 2),
},
],
}
} catch (error) {
return {
content: [{ type: 'text', text: `错误: ${error.message}` }],
isError: true,
}
}
}
})
// 提取组件
function extractComponents(node) {
const components = []
if (node.type === 'COMPONENT') {
components.push({
id: node.id,
name: node.name,
})
}
if (node.children) {
node.children.forEach((child) => {
components.push(...extractComponents(child))
})
}
return components
}
// 提取样式
function extractStyles(node) {
const styles = {
name: node.name,
type: node.type,
}
// 尺寸
if (node.absoluteBoundingBox) {
styles.width = node.absoluteBoundingBox.width
styles.height = node.absoluteBoundingBox.height
}
// 背景色
if (node.fills && node.fills.length > 0) {
const fill = node.fills[0]
if (fill.type === 'SOLID') {
styles.backgroundColor = rgbToHex(fill.color)
}
}
// 边框
if (node.strokes && node.strokes.length > 0) {
const stroke = node.strokes[0]
styles.borderColor = rgbToHex(stroke.color)
styles.borderWidth = node.strokeWeight
}
// 圆角
if (node.cornerRadius !== undefined) {
styles.borderRadius = node.cornerRadius
}
// 文字样式
if (node.style) {
styles.fontSize = node.style.fontSize
styles.fontWeight = node.style.fontWeight
styles.textColor = rgbToHex(node.style.fills[0]?.color)
}
return styles
}
// RGB转HEX
function rgbToHex(color) {
if (!color) return null
const r = Math.round(color.r * 255)
const g = Math.round(color.g * 255)
const b = Math.round(color.b * 255)
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`
}
const transport = new StdioServerTransport()
await server.connect(transport)
修改 package.json:
{
"name": "figma-mcp-server",
"version": "1.0.0",
"type": "module",
"bin": {
"figma-mcp": "./server.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^0.5.0",
"axios": "^1.6.0"
}
}
安装到全局:
npm link
Step 5: 配置Claude Desktop
编辑配置文件:
{
"mcpServers": {
"figma": {
"command": "figma-mcp",
"env": {
"FIGMA_TOKEN": "你的Figma Token"
}
}
}
}
重启Claude Desktop。
Step 6: 使用
在Claude中:
使用 read_figma_file 读取我的Figma文件:ABC123xyz
然后找到名为 "UserCard" 的组件,提取它的样式并生成React代码。
AI会调用MCP,读取Figma文件,提取精确的设计数据,生成代码。
四、方案3:Figma Inspect导出(折中方案)
Figma有个Inspect功能,可以查看设计的CSS代码。
Step 1: 打开Inspect
- 在Figma中选中组件
- 右侧面板切换到 "Inspect" 标签
- 代码类型选择 "CSS"
Step 2: 复制CSS
Figma会显示类似这样的代码:
/* UserCard */
width: 280px;
height: 140px;
background: #ffffff;
box-shadow: 0px 2px 8px rgba(0, 0, 0, 0.1);
border-radius: 8px;
/* Avatar */
width: 64px;
height: 64px;
border-radius: 32px;
/* Name */
font-family: 'PingFang SC';
font-style: normal;
font-weight: 600;
font-size: 16px;
line-height: 22px;
color: #333333;
/* Position */
font-family: 'PingFang SC';
font-style: normal;
font-weight: 400;
font-size: 14px;
line-height: 20px;
color: #666666;
Step 3: 给AI转换
这是Figma导出的CSS,帮我转换成React组件。
【CSS】
{粘贴上面的CSS}
【要求】
1. 生成React组件和CSS Modules
2. 组件要有TypeScript类型
3. 使用Ant Design的Avatar组件
4. 布局用Flexbox
Step 4: AI生成组件
AI会根据CSS生成完整的组件代码。
五、实战案例:生成Dashboard卡片
假设有这样的设计稿
一个数据卡片,包含:
- 图标(左上角)
- 标题(大号文字)
- 数值(超大号文字)
- 增长百分比(绿色/红色,带箭头)
- 对比昨日文字(小号灰色)
方式1:截图给AI
上传截图,输入:
这是一个数据卡片组件,生成代码。
【功能需求】
1. 支持不同类型的数据(用户数、订单数、营收等)
2. 增长/下降用不同颜色(绿色上涨、红色下跌)
3. 支持点击事件
4. 支持loading状态
【技术要求】
- React + TypeScript
- Ant Design Icons
- CSS Modules
- 响应式(移动端自适应)
AI生成代码
StatCard.tsx
import { ArrowUpOutlined, ArrowDownOutlined } from '@ant-design/icons';
import { Spin } from 'antd';
import styles from './StatCard.module.css';
interface StatCardProps {
icon: React.ReactNode;
title: string;
value: number | string;
change: number;
compareText?: string;
loading?: boolean;
onClick?: () => void;
}
export default function StatCard({
icon,
title,
value,
change,
compareText = '较昨日',
loading = false,
onClick,
}: StatCardProps) {
const isPositive = change >= 0;
if (loading) {
return (
<div className={styles.card}>
<Spin />
</div>
);
}
return (
<div className={styles.card} onClick={onClick}>
<div className={styles.header}>
<span className={styles.icon}>{icon}</span>
<span className={styles.title}>{title}</span>
</div>
<div className={styles.value}>{value}</div>
<div className={styles.footer}>
<span className={`${styles.change} ${isPositive ? styles.positive : styles.negative}`}>
{isPositive ? <ArrowUpOutlined /> : <ArrowDownOutlined />}
{Math.abs(change)}%
</span>
<span className={styles.compareText}>{compareText}</span>
</div>
</div>
);
}
StatCard.module.css
.card {
padding: 24px;
background: #ffffff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
cursor: pointer;
transition: all 0.3s;
min-height: 160px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.card:hover {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
transform: translateY(-2px);
}
.header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 16px;
}
.icon {
font-size: 24px;
color: #1890ff;
}
.title {
font-size: 14px;
color: #666666;
}
.value {
font-size: 32px;
font-weight: 600;
color: #333333;
margin-bottom: 12px;
}
.footer {
display: flex;
align-items: center;
gap: 8px;
}
.change {
display: flex;
align-items: center;
gap: 4px;
font-size: 14px;
font-weight: 500;
}
.positive {
color: #52c41a;
}
.negative {
color: #ff4d4f;
}
.compareText {
font-size: 12px;
color: #999999;
}
/* 响应式 */
@media (max-width: 768px) {
.card {
padding: 16px;
min-height: 140px;
}
.value {
font-size: 24px;
}
.icon {
font-size: 20px;
}
}
使用示例
import { UserOutlined, ShoppingOutlined, DollarOutlined } from '@ant-design/icons';
import StatCard from '@/components/StatCard';
export default function Dashboard() {
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 16 }}>
<StatCard
icon={<UserOutlined />}
title="总用户数"
value="12,345"
change={8.5}
onClick={() => console.log('点击用户卡片')}
/>
<StatCard
icon={<ShoppingOutlined />}
title="今日订单"
value="234"
change={-3.2}
/>
<StatCard
icon={<DollarOutlined />}
title="今日营收"
value="¥45,678"
change={12.3}
/>
</div>
);
}
六、设计Token提取
从Figma提取颜色规范
方式1:手动整理
在Figma中,左侧有 "Local styles",可以看到所有颜色。
记录下来:
Primary: #1890FF
Success: #52C41A
Warning: #FAAD14
Error: #FF4D4F
Text/Primary: #333333
Text/Secondary: #666666
Text/Disabled: #999999
Border: #D9D9D9
Background: #F0F2F5
方式2:用Figma API提取
// 在MCP Server里添加
async function getStylesFromFile(fileKey) {
const response = await axios.get(
`https://api.figma.com/v1/files/${fileKey}/styles`,
{
headers: { 'X-Figma-Token': FIGMA_TOKEN },
}
)
const styles = response.data.meta.styles
const colors = {}
for (const style of styles) {
if (style.style_type === 'FILL') {
colors[style.name] = await getStyleColor(fileKey, style.node_id)
}
}
return colors
}
生成Design Tokens文件
拿到颜色后,让AI生成:
根据这些颜色生成Design Tokens文件。
【颜色】
Primary: #1890FF
Success: #52C41A
...
【要求】
1. 生成CSS变量版本
2. 生成TypeScript对象版本
3. 生成Tailwind配置版本
AI会生成:
tokens.css
:root {
--color-primary: #1890ff;
--color-success: #52c41a;
--color-warning: #faad14;
--color-error: #ff4d4f;
--color-text-primary: #333333;
--color-text-secondary: #666666;
--color-border: #d9d9d9;
--color-background: #f0f2f5;
}
tokens.ts
export const colors = {
primary: '#1890FF',
success: '#52C41A',
warning: '#FAAD14',
error: '#FF4D4F',
text: {
primary: '#333333',
secondary: '#666666',
disabled: '#999999',
},
border: '#D9D9D9',
background: '#F0F2F5',
} as const
tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: '#1890FF',
success: '#52C41A',
warning: '#FAAD14',
error: '#FF4D4F',
},
},
},
}
七、常见问题
Q1: AI识别的尺寸不准确怎么办?
方法1: 在截图上标注尺寸
用Figma的测量工具(Alt/Option拖动),显示间距,然后截图。
方法2: 明确告诉AI
卡片宽度不是280px,是300px。内边距是20px不是16px。
Q2: 复杂布局AI生成不对怎么办?
分步骤
第一步:先生成整体布局,不要细节
第二步:逐个生成内部组件
第三步:组合起来
Q3: 设计稿有动画效果,AI能生成吗?
可以,但需要你描述:
这个卡片hover时有动画:
1. 阴影从2px变成4px
2. 整体向上移动2px
3. 过渡时间0.3秒
请加上这些动画。
Q4: 响应式怎么处理?
告诉AI断点:
断点:
- 移动端:< 768px
- 平板:768px - 1024px
- 桌面:> 1024px
移动端:
- 卡片宽度100%
- 字体缩小2px
- 内边距减少
八、实用技巧
技巧1:建立设计规范库
把常用的设计元素整理成文档:
# 设计规范
## 颜色
- Primary: #1890FF
- ...
## 间距
- xs: 4px
- sm: 8px
- md: 12px
- lg: 16px
- xl: 24px
## 圆角
- small: 4px
- medium: 8px
- large: 12px
## 字体
- h1: 32px, 600
- h2: 24px, 600
- body: 14px, 400
- small: 12px, 400
每次让AI生成组件时,附上这个规范。
技巧2:截图带标注
Figma有个功能叫 "Redlines"(标注线),开启后截图,AI能看到精确尺寸。
技巧3:先低保真,再高保真
第一步:用简单的线框图生成基础结构 第二步:加上设计稿细节
这样AI生成的代码结构更清晰。
九、总结
Figma转代码的三种方案对比:
| 方案 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| 截图+AI | 最简单,马上能用 | 尺寸可能不准 | 快速原型 |
| Figma API | 数据最准确 | 需要开发MCP | 大型项目 |
| Inspect导出 | 有官方支持 | 需要手动操作 | 中小项目 |
建议
- 新手从截图开始
- 熟练后用Inspect
- 团队项目考虑开发MCP
核心思路:让AI看到设计,AI就能生成代码。 不管用哪种方式,把设计给AI看,比你自己对着设计稿敲代码快得多。