Vue3 还原一个企业级后台-03-Figma 数据提取:用 MCP 工具读懂设计稿
Figma 数据提取:用 MCP 工具读懂设计稿
设计师用 Figma 画图,前端用 Figma 还原。但"还原"不是"照着画"——你要先"读懂"设计稿里的每一个像素、每一个颜色、每一个间距,然后才能把它们变成代码。这篇文章,就讲"读"这一步。
一、Figma 不是图片,是一棵数据树
很多人拿到 Figma 设计稿,第一反应是截图然后照着写代码。这是前端还原最常见的误区。
Figma 的真正价值不在于"画得像",而在于它的每一个元素都是结构化数据。一个 Figma 文件本质上是一棵巨大的 JSON 树——每个画布是一个节点,画布里的每个 Frame 是一个子节点,Frame 里的每个矩形、文本、图标又是更深层的叶子节点。
它的数据结构大致长这样:
Figma 文件(对应一个 fileKey)
├── Canvas "登录"(页面级)
│ ├── FRAME "登录页"(nodeId: 17:8)
│ │ ├── RECTANGLE "背景"(x:0, y:0, w:1920, h:1080, fill:#C8E1FF)
│ │ ├── TEXT "管网模型工具"(fontSize:26, fontFamily:MiSans, fill:#333)
│ │ ├── RECTANGLE "登录按钮"(cornerRadius:14, fill:#0073FB)
│ │ └── INSTANCE "输入框组件"(引用 componentId: 123:45)
│ └── ...
├── Canvas "API 管理"
│ ├── FRAME "注册管理列表"(nodeId: 19:2)
│ ├── FRAME "注册管理-详情"(nodeId: 19:3)
│ └── FRAME "注册管理-弹窗"(nodeId: 19:4)
├── Canvas "模型汇聚"
│ └── ... 6 个 frame
└── Canvas "模型标准发布"
└── ... 3 个 frame
每个节点都携带了完整的元数据:坐标(absoluteBoundingBox)、尺寸、填充色、描边、圆角、字体、字号、字重、阴影、透明度、子节点列表、组件引用等。
换句话说,设计师在 Figma 里拖拽的每一步,都变成了这棵树上的一个节点和一组属性。前端要做的,就是把这棵树"翻译"成 HTML + CSS。
二、Figma MCP:把设计稿变成可编程数据
“知道了,Figma 是 JSON 树。但怎么拿到这棵 JSON 树?”
传统的做法是:在 Figma 里用 Dev Mode,一个一个选节点,看右边面板的 Inspect 属性,然后手动抄到代码里。对于一个有 17 个 Frame、几百个节点的项目,这个工作量足以让任何人崩溃。
好在我们有 Figma MCP 工具——它把 Figma 的 REST API 封装成了可以直接在开发环境中调用的接口。核心是两个能力:
2.1 读取设计文件结构:get_figma_data
这个工具接收一个 fileKey(Figma 文件的唯一标识,可以从 URL 里拿到),返回整个文件的完整节点树。
用法极其简单:
get_figma_data(fileKey="OE9epSjwXFXa4PTuwdgkSK")
返回的是一个 YAML 格式的完整节点树,包含所有画布、Frame、组件、文本、矩形、矢量的全部属性——位置、尺寸、颜色、字体、圆角、阴影、层级关系,一个不落。
我们这个项目的设计文件,返回的数据量约 1.5MB。这听起来很大,但考虑到它包含了 17 个完整页面的所有细节信息,其实是相当紧凑的。
2.2 导出图标和图片:download_figma_images
除了"读数据",还能"下载资源"。设计稿中用到的图标,在这个工具看来就是一组 nodeId——传入节点 ID 和导出格式,就能把 SVG 或 PNG 下载到本地。
download_figma_images(
fileKey="OE9epSjwXFXa4PTuwdgkSK",
nodes=[{"nodeId": "232:45", "format": "svg"}]
)
这两个工具加起来,就把 Figma 从一个"只能看"的设计工具,变成了一个"可以编程读取"的数据源。这是整个项目工程化的起点。
三、实操:从 1.5MB YAML 里捞出有效信息
拿到 1.5MB 的 YAML 数据后,问题变成了:怎么从这个庞大的数据里提取出我需要的东西?
我的做法分三步。
第一步:梳理顶层结构——有哪些 Canvas?
不需要写代码。直接看 YAML 的第一层级,就能看到这个文件的所有 Canvas(也有的 Figma 文件中叫 Page):
name: 管网模型工具 (Copy)
lastModified: "2025-xx-xx"
document:
children:
- name: "登录" # Canvas 1
- name: "API 管理" # Canvas 2
- name: "模型汇聚" # Canvas 3
- name: "模型标准发布" # Canvas 4
立刻就能搞清楚:这个设计文件有 4 个 Canvas,分别对应 4 个业务模块。
第二步:统计每个 Canvas 下的 Frame
继续往下钻。每个 Canvas 的 children 里就是一个个 Frame(设计稿里的"页面"):
Canvas "API 管理":
children:
- FRAME "注册管理" (nodeId: 19:2)
- FRAME "注册管理-默认" (nodeId: 19:3) # ← 同一页面的不同状态
- FRAME "注册管理-选中" (nodeId: 19:4)
- FRAME "注册弹窗-新增" (nodeId: 19:5)
- FRAME "注册弹窗-编辑" (nodeId: 19:6)
- FRAME "详情-基本信息" (nodeId: 19:7)
- FRAME "详情-运行调试" (nodeId: 19:8)
- FRAME "详情-编辑弹窗" (nodeId: 19:9)
同理遍历其他 Canvas:
- 模型汇聚 Canvas:6 个 Frame
- 模型标准发布 Canvas:3 个 Frame
- 登录 Canvas:1 个 Frame
合计:17 个 Frame。这个数字很重要——它决定了这个项目的页面规模,也决定了后续的组件设计和开发排期。
第三步:对每个 Frame 做关键属性提取
有了 Frame 清单以后,逐个看每个 Frame 的直接属性,提取出布局相关的核心参数。以"登录"Frame 为例:
FRAME "登录页":
absoluteBoundingBox: { x:0, y:0, width:1920, height:1080 }
fills: [{ color: { r:0.784, g:0.882, b:1.0 } }] # #C8E1FF
cornerRadius: 0
children:
- TEXT "管网模型工具":
style:
fontFamily: "MiSans"
fontSize: 26
fontWeight: 700
fills: [{ color: { r:0.2, g:0.2, b:0.2 } }] # #333333
- RECTANGLE "登录框":
fills: [{ color: { r:1, g:1, b:1 } }] # #FFFFFF
cornerRadius: 14
strokes: [{ color: { r:0.78, g:0.88, b:1 } }]
- INSTANCE "按钮":
componentId: "232:38"
从这几行里,我已经能提取出:
- 页面尺寸:1920 × 1080(设计稿基准分辨率)
- 背景色:
#C8E1FF - 字体:MiSans, 26px, Bold,
#333333 - 卡片圆角:14px
- 组件引用:按钮用的是
componentId: 232:38(这意味着它是一个可复用的组件实例)
同样的方法遍历所有 17 个 Frame,就能建立一份完整的"页面属性清单"。
四、关键发现:17 个 Frame 的业务全景
把 17 个 Frame 的信息汇总之后,整个项目的业务结构就清晰了:
管网模型工具(17 Frame)
│
├── 登录模块(1 Frame)
│ └── 登录页
│
├── API 管理模块(8 Frame)
│ ├── 列表:注册管理/默认/选中(3 个状态变体)
│ ├── 弹窗:新增/编辑(2 个变体)
│ └── 详情:基本信息/运行调试/编辑弹窗(3 个页面)
│
├── 模型汇聚模块(6 Frame)
│ ├── 列表:模型汇聚
│ ├── 详情:接口Tab/模型文件Tab/命令行脚本Tab
│ ├── 新增:多步骤表单
│ └── ...
│
└── 模型标准发布模块(3 Frame)
├── 列表:发布管理
├── 详情:基本信息
└── 弹窗:发布确认
这个全景图的价值在于:你在写第一行代码之前,就已经对整个项目的页面结构了如指掌。后续做路由设计、组件拆分、目录规划时,这张全景图就是你的地图。
而且,越是仔细读设计稿,你越能发现设计师隐藏的表达。比如:
- API 管理的列表页有三个 Frame 变体(默认、选中、全选),说明这里要支持复选框联动——后面写代码时必须实现。
- 弹窗分"新增"和"编辑"两个 Frame,布局完全一致,说明可以复用同一个弹窗组件——组件设计时要考虑"模式"参数。
- 登录页有一个独立的 Canvas,意味着登录和主业务是两个不同的布局——路由设计时要做区分。
读懂设计稿的过程,就是理解业务逻辑的过程。
五、提取设计 Token:把散落的属性聚合成系统
前面提到的颜色、字体、圆角等属性,在 17 个 Frame 中反复出现。如果每个 Frame 都单独写 color: #0073FB,改一个主色就要全局搜索替换——这是灾难。
所以,在"读 Figma"这一步,我专门做了一件事:把所有 Frame 中出现过的样式值汇总、去重、归并,提取出一套设计 Token。
5.1 颜色 Token
遍历所有 Frame 的 fills 和 strokes,整理出真正的色板:
| 用途 | 色值 | 变量名 |
|---|---|---|
| 页面背景 | #C8E1FF |
--color-bg-page |
| 卡片/容器背景 | #F0F5FC |
--color-bg-card |
| 主色/品牌色 | #0073FB |
--color-primary |
| 主色悬停 | #005FCF |
--color-primary-hover |
| 主色浅背景 | #E8F1FE |
--color-primary-light |
| 成功/启用 | #52C41A |
--color-success |
| 文字主色 | #333333 |
--color-text-primary |
| 文字次要 | #666666 |
--color-text-secondary |
| 文字辅助/占位 | #999999 |
--color-text-placeholder |
| 边框色 | #D9D9D9 |
--color-border |
虽然 17 个 Frame 的表面上看用了"50+ 种颜色",但去掉透明度变体、渐变叠加后,核心的系统色只有 10 个左右。这 10 个颜色就是后续 CSS 变量的基础。
5.2 字体 Token
| 用途 | 字体 | 备用 |
|---|---|---|
| 中文字体 | MiSans / AlibabaPuHuiTi | PingFang SC, Microsoft YaHei |
| 英文/数字字体 | Inter | -apple-system, sans-serif |
| 代码字体 | — | Consolas, monospace |
5.3 字号阶梯
| Token | 数值 | 使用场景 |
|---|---|---|
--font-size-xl |
26px | 页面大标题 |
--font-size-lg |
18px | 模块标题 |
--font-size-md |
16px | 正文、表格内容 |
--font-size-sm |
14px | 辅助文字、标签 |
--font-size-xs |
12px | 注释、徽标 |
5.4 圆角阶梯
| Token | 数值 | 使用场景 |
|---|---|---|
--radius-lg |
14px | 卡片、弹窗 |
--radius-md |
10px | 输入框、按钮 |
--radius-sm |
8px | 标签、徽标 |
--radius-xs |
6px | 小按钮、下拉菜单 |
5.5 间距阶梯
4px / 8px / 12px / 16px / 24px / 32px / 40px / 50px
这些 Token 现在看起来只是一堆数字,但下一篇(设计系统建设)你会看到,它们会被写入一个 tokens.css,然后通过 SCSS 变量覆写到 Element Plus 上。从此以后,你不需要再手写 #0073FB 或 14px——调一个变量,全局生效。
六、导出图标:SVG 的坑和绕法
除了样式数据,Figma 里的图标也是需要"搬"到代码里的资源。
用 download_figma_images 导出图标理论上很简单:
download_figma_images(
fileKey="OE9epSjwXFXa4PTuwdgkSK",
nodes=[{"nodeId": "232:45", "format": "svg"}]
)
但在实际操作中遇到了两个典型问题。
问题一:嵌套结构导致 SVG 渲染异常
有些图标在 Figma 里是"FRAME 里套 Vector"的结构。直接导出时,外层的 FRAME 会被渲染成一个 <svg> 容器,内部的 Vector 被渲染成 <path>,但定位信息可能丢失,导致图标位置偏移。
处理方式:对于这类嵌套节点,先看它的子节点是不是纯 Vector。如果是,就取最内层的 Vector 节点 ID 作为导出目标,跳过外层的 FRAME 包装。
问题二:Component 类型无法直接导出
Figma 中的组件(Component)在 API 层面被标记为不同的类型。download_figma_images 对 Component 类型的节点支持有限,有时会返回失败。
处理方式:对于 Component 类型的图标,先通过 get_figma_data 查看它的 children,找到具体渲染的矩形或矢量节点,再用子节点的 ID 导出。另一种方案是直接用 Chrome 开发者工具在 Figma 页面上手动导出——毕竟图标数量通常不多(本项目约 20 个左右),手动操作的成本可控。
实际项目中,我最终的图标获取流程是:
- 从 YAML 中提取所有 COMPONENT 类型的节点及其名称
- 按名称判断是否为图标(
icon-xxx/xxx-icon等命名规律) - 能通过 MCP 导出的优先自动导出到
src/assets/icons/ - 导出失败的(约 3-4 个),在 Figma 页面手动导出 SVG
七、从"读"到"写":数据提取的输出物
到这里,Figma 数据提取阶段的工作就完成了。回头看,我得到了四样东西:
| 输出物 | 内容 | 用途 |
|---|---|---|
| Canvas 与 Frame 清单 | 4 个 Canvas、17 个 Frame 的完整列表 | 路由设计、目录规划 |
| Frame 属性清单 | 每个 Frame 的尺寸、背景色、关键样式 | 布局组件开发 |
| 设计 Token 汇总表 | 颜色/字体/字号/圆角/间距的完整映射 | CSS 变量定义、主题覆写 |
| 图标资源 | 约 20 个 SVG 图标文件 | 组件开发 |
这些东西看起来是"数据",本质上它们是后续所有开发工作的"规格书"。没有这份规格书就开始写代码,就像没有施工图就开始盖楼——可能也能盖起来,但一定到处都是补丁。
八、小结:前端工程师的"读图能力"
最后想聊一个认知。
很多前端工程师认为自己的核心技能是"写代码"。但在这个项目里,我发现一个更高阶的能力:从非结构化输入中提取结构化信息。
Figma 设计稿是设计师的表达,它是视觉化的、直觉化的、有时甚至是不完全一致的(同一个颜色在不同 Frame 里可能有微小差异)。前端要做的不是"照着画",而是:
- 发现规律(10 个系统色 vs 50+ 种视觉颜色)
- 建立映射(设计 token → CSS 变量 → Element Plus 主题)
- 洞察意图(三个 Frame 变体 = 复选框联动需求)
"看 Figma"是设计师的事。"读 Figma"是工程师的事。前者用眼睛,后者用脑子。
上一篇:02 - 技术选型:Vue3 vs React,为什么选 Element Plus
下一篇预告:设计 Token 提取完了,下一步是把它们变成可以用的 CSS 变量,再覆写到 Element Plus 主题上。一个变量改颜色、全局生效的设计系统,是怎么搭出来的?
更多推荐


所有评论(0)