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 的 fillsstrokes,整理出真正的色板:

用途 色值 变量名
页面背景 #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 上。从此以后,你不需要再手写 #0073FB14px——调一个变量,全局生效。


六、导出图标: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 个左右),手动操作的成本可控。

实际项目中,我最终的图标获取流程是:

  1. 从 YAML 中提取所有 COMPONENT 类型的节点及其名称
  2. 按名称判断是否为图标(icon-xxx / xxx-icon 等命名规律)
  3. 能通过 MCP 导出的优先自动导出到 src/assets/icons/
  4. 导出失败的(约 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 主题上。一个变量改颜色、全局生效的设计系统,是怎么搭出来的?

Logo

欢迎加入 MCP 技术社区!与志同道合者携手前行,一同解锁 MCP 技术的无限可能!

更多推荐