AI 生码 - D2C:Figma to Code 全流程实现

一、背景描述

1.1 概念介绍

D2C 技术(Design to Code,设计到代码),核心是将 Figma、视觉稿图片等视觉设计文件,转换为 HTML、CSS 等前端产物,最终组合渲染为完整页面或局部模块的技术。

1.2 业界方案调研

业界 D2C 方案主要分为图生码(Image To Code)和插件生码(Figma To Code)两大方向,技术路径与适配场景各有侧重。

1.2.1 图生码(Image To Code)

图生码依托 AI 大模型识别视觉稿中的组件类型与样式布局,还原重组为 React 源代码(JSX + CSS),核心依赖 IR 中间描述协议实现转换。

1.2.1.1 流程示意

视觉稿图
解析内容
生成IR协议
IR分析/映射/处理
React源码(JSX+CSS)
低代码组件schema

1.2.1.2 IR协议详解

IR协议核心定位
编译原理衍生的通用数据结构(与源/目标语言无关,通用适配)
D2C场景核心桥梁:视觉稿→前端产物
核心用途:分析变换、解释执行
上层:贴近源代码语义
下层:贴近目标代码语义

1.2.1.3 工具对比

图生码主流工具核心对比如下:

业界方案 核心信息 样式还原 生码速度 组件识别 代码质量 定制化支持 训练数据/能力开放情况
V0 收费未开源,Versel 产品,不支持自定义组件库 极快
WeaveFox 收费未开源,蚂蚁多模态产品,依赖私有模型 快速 部分
云凤蝶 免费开源,中后台低代码搭建工具 快速

注:WeaveFox 宣称可 1:1 视觉还原,可参考模型评测链接:https://www.yuque.com/weavefox/intro/ranking-of-sota-models

1.2.2 插件生码(Figma To Code)

1.2.2.1 流程示意

Figma设计稿
通过Figma API获取设计稿信息
提取IR中间描述
代码生成层处理
输出目标前端代码

1.2.2.2 工具对比

可参考:AI 生码 - D2C:主流设计转代码工具对比

工具名称 收费/开源 核心特点
Anima 是/否 使用量最高,还原度、代码质量高,支持三方组件库
Bolt.dev 是/否 交互类 Anima,支持三方开源组件库,集成 AI 编码
Builder.io 是/否 协同型工具,还原度、代码质量略逊于 Anima
Figma to AI Code 否/否 AI 驱动,需自备 OpenAI 账户,适配个人项目
Figma to Code 否/是 基础转码,效果一般,支持二次开发
Semi Design 否/否 字节开发,稳定可靠,支持三方组件库
Figma-Context-MCP 否/是 基于 Figma API 封装,使用便捷,还原度一般

总结:免费工具还原度、定制化支持一般;收费工具能力更优,适配企业级场景;开源工具适合定制化开发。

1.3 思考与取舍

业界 D2C 方案多聚焦 C 端,B 端与 C 端需求差异显著,需结合场景、技术路线及用户习惯合理取舍。

1.3.1 C2D(Code to Design,代码转设计稿)的取舍

C2D 作为 D2C 前置流程,可自动生成设计资产、节省设计师维护成本,核心价值是保持设计与代码同步,更适配变体多、主题定制多的 C 端场景,对 B 端收益有限。

1.3.2 设计师使用习惯适配

现有 Figma 平台 C2D 工具多需通过插件操作组件实例,与设计师习惯的 Variant 变体切换方式不符,会降低效率,需重点适配。

1.3.3 技术路线选择(图转码 vs 插件生码)

结合 B 端需求,对比图转码与插件生码两种 D2C 技术路线,其中插件生码搭配 AI 优化,是兼顾视觉还原度与代码可用性的最优选择,两者具体对比如下:

Image to Code(图转码)
  • 传统路线:依赖 YOLO 切割元素,相似组件识别准确率低,还原度难以突破;
  • 大模型路线:适配特定设计系统能力弱,视觉细节偏差大,验收与改善成本高。
Figma to Code(插件生码)

结构化信息转换,相似组件、设计系统识别精准,解决图转码痛点,是当前业界主流,更适配 B 端场景。

二、任务目标

2.1 方案价值

  • 提效:替代 HTML、CSS 等劳动密集型工作,减少人工投入;
  • 保一致:统一设计源文件,减少设计与开发沟通误差;
  • 高自动化:素材到代码转换无需大量人工二次调整。

2.2 指标设置

围绕标注侧、工程侧、Agent 侧,设置可量化、可验证的核心指标:

维度 目标 指标 定义
标注侧 Figma UI 标准化 标注覆盖率 已标注组件数/总组件数
组件复用率 复用组件数/总使用组件数
标注完整度 组件属性、交互标注完整性
工程侧 Figma UI 映射研发语义 组件映射准确率 设计组件正确映射研发组件比例
生成布局相似率 代码 UI 与设计稿相似度
一次生成成功率 无需手动修复即可运行代码比例
Agent 侧 代码标准化 平均响应时间 从输入到输出代码的时间
代码质量评分 可读性、冗余度、lint 规则符合度
模型成本 模型运行消耗的费用

三、Figma to Code 整体设计

3.1 名词解释

明确核心名词,统一认知:

名词 解释
组件(Component) 可重复使用的设计元素(按钮、图标等)
属性(Properties) 区分变体差异的命名参数(颜色、尺寸等)
变体(Variants) 同一组件的不同状态/配置(如按钮的默认/禁用状态)
组件集(Component Set) 多个变体的集合
实例(Instance) 组件的复用副本,继承组件属性,可自定义修改

3.2 转换原理

Figma to Code 可实现,核心是 Figma 与 Web 渲染引擎高度相通,为属性映射提供基础:

  • 统一数学基础:笛卡尔坐标、几何变换矩阵、RGBA 颜色模型等;
  • 相似树状结构:Figma 节点树对应 Web DOM 树;
  • 一致渲染流程:均遵循「解析→样式计算→布局→绘制→合成」流程。

基于以上共性,Figma 属性可与 CSS 属性精准映射,完成设计稿到代码的转换。

3.3 整体流程

遵循「标注先行、协同联动」思路,分为两大核心阶段:
整体流程:标注先行+协同联动
标注阶段
研发阶段
与产品同学约定Figma UI标准化规范
研发遵循标注语法(含图层、变体命名规范)标注组件库
业务产品同学使用已标注组件库生成业务视觉稿
业务研发同学获取产品生成的业务视觉稿
通过「Copy link to selection」获取视觉稿链接
打开编辑器插件,粘贴链接+输入提示词
生成代码
D2C Agent侧【代码标准化】
D2C工程侧【Figma UI映射研发语义】
标注侧【Figma UI标准化】
标注Figma组件
标注内置
提供标注元数据
动作/计划
figma url + 指令
Code
get_code_by_figma_url
领域小模型微调
基座模型
高质量数据集
训练&评测
提示词工程
样式提取
组件化拆分
提示词n...
AI物料知识库
基础组件库
业务组件库
移动端组件库
样板间资产物料
Agent矩阵
IR2Code Agent
代码优化Agent
质检Agent
DEV开发者
设计师+DEV
UI组件库

SPC UI Icon / SPC UI React / React Pro Components等
MetaData中心
协议解析
节点树提取
组件映射
标注映射
标注绑定
标注解析
路径提取
变体属性映射
动态属性映射
特征提取
二维投影
加权评分
布局生成
行列分组
盒模型生成
AST Nodes
AST Builder
JSX Code
Agent侧入口
模型推理
工具调用

3.4 技术架构

本方案采用「标注侧→D2C 工程侧→D2C Agent 侧」三层解耦架构,各模块职责清晰、协同闭环,实现从 Figma 设计标注到标准化前端代码输出的全流程自动化,架构流程与详细说明如下:
D2C Agent侧
工具调用
语义泛化
组件封装
类名优化
D2C工程侧
代码预生成
Code Generate
样式生成
AST 构建
AST Node
标注解析
动态属性计算
路径映射
组件映射
标注绑定
自动布局
齐次坐标系
添加父子关系
图片识别
特征提取
行列分割
节点矩形化
自动分组
盒模型生成
标注侧
postMessage
批量标注
插件UI
插件沙箱

3.4.1 各层核心职责

标注侧:Figma UI 标准化前置支撑

核心负责 Figma 设计资产标准化标注,通过 D2C Plugin 插件实现批量标注、UI 交互及沙箱通信,确保标注信息可解析,为后续转码减少误差。

D2C 工程侧:设计与研发的核心转换桥梁

承接标注侧资产,完成 Figma UI 到研发语义的映射,分 3 个子模块协同工作:

  • 标注解析:解析标注信息,衔接标注侧与工程侧;
  • 自动布局:梳理节点关系、提取特征,还原设计稿布局;
  • 代码预生成:输出基础 AST Node,为 Agent 侧优化提供支撑。
D2C Agent 侧:代码标准化保障

承接工程侧基础代码,通过工具调用、语义泛化、组件封装及类名优化,输出可直接集成的标准化代码,降低人工修改成本。

3.4.2 协同逻辑与核心优势

协同逻辑

三层架构形成闭环:标注侧输出标准化资产→工程侧完成设计转基础代码→Agent 侧优化代码,同时反向反馈问题、持续迭代,提升转码质量。

核心优势
  • 分层解耦:模块独立,便于单独迭代,降低维护成本;
  • 闭环迭代:全流程可反馈、可优化,转码效果持续提升;
  • 适配 B 端:针对性解决设计标准化、组件映射精准性等核心痛点;
  • 高自动化:全流程无需大量人工干预,降低使用门槛。

4. 详细设计

4.1 组件标注

组件标注的核心是解决 D2C 还原阶段 Figma 节点与研发侧组件属性的映射问题,确保设计资产可精准解析为规范代码,分为 Figma UI 标准化与标注解析两大环节。

4.1.1 Figma UI 标准化

  • 标注人员掌握标注语法、参考标注案例定义图层及变体属性规范(组件库包含数百个组件,「 D2C Plugin 」支持组件集批量标注以降低工作量);
  • 组件库标准化及标注完成后,后续产品人员使用该组件库生成业务视觉稿。

4.1.2 解析标注

标注完成后生成的 metaData,是 D2C 转换的核心数据依据,其 TypeScript 类型定义如下:

typescript 复制代码
/**
 * 组件元数据类型( D2C 转换核心数据依据)
 */
interface MetaData {
    packageName: string; // 组件所属包名
    componentName: string; // 组件名称(与研发侧组件对应)
    props: Record<string, any>; // 研发侧组件固定属性
    dynamicProps: Array<MetaDataDynamicProp>; // 自定义内容识别用动态属性
    style?: Record<string, any>; // 组件样式( D2C 转换时合并至节点)
    dynamicComponentName?: string; // 动态标记的组件名称
    toTemplate?: ToTemplate; // 自定义节点渲染模板
    dependencies?: Dependency[]; // 组件依赖项列表
}

以 Button 组件的 metaData 为例:

typescript 复制代码
/**
 * @param component Figma 组件节点(含变体属性)
 * @return 组件元数据( MetaData )
 */
function metaDataFactory(component) {
  const { variantProperties: figmaVariantProps } = component; // Figma 组件变体属性
  // 解构 Figma 变体属性,前缀 figma 区分 Figma 侧与研发侧
  const { type: figmaBtnType, size: figmaBtnSize, status: figmaBtnStatus } = figmaVariantProps;
  
  // Figma 组件类型 → 研发侧 Button 组件类型映射表
  const figmaToDevTypeMap = {
    'fill': 'primary',    // 填充型 → 主按钮
    'outlint-secondary': 'default', // 次要描边 → 默认按钮
    'textButton-blue': 'link'      // 蓝色文本 → 链接按钮
  };
  
  return {
    packageName: "spc-ui-react",
    componentName: "Button",
    props: {
      size: figmaBtnSize, // 尺寸映射( normal/large/small )
      disabled: figmaBtnStatus === 'disabled', // 禁用状态( Figma 状态匹配)
      loading: figmaBtnStatus === 'spin', // 加载状态( Figma 状态匹配)
      type: figmaToDevTypeMap[figmaBtnType], // 组件类型映射
      ghost: figmaBtnType === 'outlint-primary' // 幽灵按钮( Figma 描边类型匹配)
    },
    dynamicProps: [
      { key: 'children', type: 'TEXT', path: 'Label' } // 按钮文本(动态映射 Figma Label 图层)
    ],
    style: {}
  };
}

metaData 解析的核心是将选中节点与 metaData 绑定,解析静态、动态属性后,将生成的 resolvedProps 与原始节点绑定。静态属性( metaData.props )解析简单,主要处理变体属性映射; dynamicProps 解析较复杂,完整流程如下:
数据注入
动态属性解析
resolveMetadata
节点树
绑定
MetaData

组件标注
NodeTree

原生节点树
dynamicProps

属性数组
路径解析

path:'Text Button'
类型处理

type:'TEXT'
属性映射

key:title
resolvedProps

解析完成属性
SceneNodeWithMetadata

元数据场景节点
增强节点

NodeWithResolvedProps

4.2 数据提取

数据提取是 D2C 转换的核心前提,主要包括 Figma 节点树提取(含样式属性)、组件映射,同时针对特殊场景提供补偿映射方案

4.2.1 提取 Figma 节点树

  1. 通过 Figma REST API 获取节点信息,需提前申请 API token(参考Access Tokens);
  2. 在 Figma 中通过「 Copy link to selection 」获取目标区域链接;
  3. D2C 过程中,携带 plugin Id 请求 Figma REST API,解析后得到的节点信息核心结构如下,其本质是含布局、样式的递归树状结构,聚焦设计师语义:
json 复制代码
{
  "nodes": {
    "343:15436": {
      "document": { ... }, // 主体节点树, Figma 节点结构
      "components": { ... }, // 所有定义的组件实例
      "componentSets": { ... }, // 用到的 Figma 组件库
      "schemaVersion": 0,
      "styles": { ... } // 颜色、字体、阴影等样式定义
    }
  }
}

document 的核心内容如下,据此可映射面向 Web 开发的 IR 中间协议:

  • 节点类型: FRAME (框架)、 TEXT (文本)、 INSTANCE (组件实例)、 GROUP (分组);
  • 样式系统: fills (填充)、 strokes (描边)、 style (基础样式)、 layoutMode (布局模式);
  • 布局信息: autolayout 描述、 primaryAxisAlignItems (主轴对齐方式)、 counterAxisAlignItems (反轴对齐方式);
  • 组件机制: COMPONENT/INSTANCE (组件/实例),指向元组件定义,通过名称或插件注入,不绑定事件。

4.2.2 组件映射

Figma 组件实例以 INSTANCE 类型标识,核心是建立其与研发侧组件的映射,核心逻辑为「实例→组件→组件集→研发侧组件」,以下结合各层级数据及映射关系详细说明。

  1. Figma INSTANCE 节点(映射 componentId)
typescript 复制代码
const figmaInstanceNode = {
  id: '<nodeId>', // 节点唯一标识
  name: 'Select', // 组件实例名称
  type: 'INSTANCE', // 节点类型:组件实例
  scrollBehavior: 'SCROLLS', // 滚动行为
  componentId: '<figmaComponentId>', // 核心:关联 Figma 组件的唯一标识,用于映射至组件数据
  componentProperties: { // 组件变体属性
    Property1: {
      value: 'Filter',
      type: 'VARIANT',
      boundVariables: {}
    }
  }
};
  1. Figma COMPONENT 数据(映射 componentSetId)
typescript 复制代码
const figmaComponentData = {
  components: {
    '561:5726': { // componentId,组件唯一标识
      key: '35e443087edc00d56ade91856bae6405d3b8fd49', // 组件唯一 key
      name: 'Property1=Filter', // 组件名称(含变体属性)
      description: '', // 组件描述
      remote: true, // 是否为远程组件
      componentSetId: '<figmaComponentSetId>', // 核心:关联组件集的唯一标识,用于映射至组件集数据
      documentationLinks: [] // 文档链接
    },
    '81:58': { // 其他组件示例(非核心,仅作参考)
      key: 'e5911df13dcebf6fd6afed7d868f4241b706b619',
      name: 'Down',
      description: '',
      remote: true,
      documentationLinks: []
    }
  }
};
  1. Figma COMPONENT SET 数据(映射 componentName)
typescript 复制代码
const figmaComponentSetData = {
  componentSets: {
    '561:5709': { // componentSetId,组件集唯一标识
      key: '59d4e49c80355219ef98841c8d5c8d497593c96f', // 组件集唯一 key
      name: '<figmaComponentName>', // 核心:组件集名称,用于映射至研发侧组件库(最终映射目标)
      description: '', // 组件集描述
      remote: true // 是否为远程组件集
    }
  }
};
  1. 研发侧组件库: SPC UI React 、 React Pro Components 等

完整层级映射流程为: Figma 实例节点→通过 componentId 映射至 Figma 组件数据→通过 componentSetId 映射至 Figma 组件集数据→通过 componentName 映射至研发侧组件库。

组件解绑

Figma 组件、实例与 pluginData 的关联逻辑:实例通过 mainComponent 引用关联组件;解绑后实例转为普通 Frame 节点,失去该引用,且 Figma 会生成 DetachedInfo,记录原始组件 Id 及所属 library 信息,便于追溯。
1:N
mainComponent
setPluginData
继承 Plugin Data


COMPONENT(组件)
INSTANCE(实例)
Figma Plugin( Plugin API )
实例是否解绑?
保持 INSTANCE 类型,正常映射组件
失去 mainComponent 引用,为普通 Frame 节点
生成 DetachedInfo,记录原始 componentId 和 library 信息

4.2.3 补偿映射

针对未标注组件、解绑后无法映射 componentSet 的场景(如存量设计稿图层命名不规范),提供补偿映射方案:建立组件特征库,通过多维度特征加权评分,≥ 0.6 即判定为对应组件。

补偿映射核心特征及权重:

  • 语义命名:基于组件名称关键词匹配(正则+关键词列表),权重 0.4-0.9;
  • 内部结构:基于组件内部布局、子元素特征,权重 0.6-0.9;
  • 几何坐标:基于节点几何坐标聚类识别行列结构,权重 0.6-0.8。
4.2.3.1 语义检测

以 Table 组件为例,通过正则匹配节点 name 关键词并分配权重,实现语义识别,核心代码如下:

typescript 复制代码
// Table 组件语义检测规则(关键词匹配+权重,用于补偿映射评分)
private static initializeTableRules(): void {
  // key: 目标组件类型,value: 关键词匹配规则(含权重)
  this.rules.set('table', [
    { pattern: /pro.?table/i, weight: 0.9, caseSensitive: false, language: 'en' }, // 高权重: ProTable (研发常用组件)
    { pattern: /table|data.?table/i, weight: 0.8, caseSensitive: false, language: 'en' }, // 常规: table/dataTable
    { pattern: /表格|数据表/, weight: 0.7, caseSensitive: false, language: 'zh' }, // 中文:表格/数据表
    { pattern: /grid|网格/, weight: 0.6, caseSensitive: false }, // 关联匹配:网格(中英文通用)
    { pattern: /list|列表/, weight: 0.4, caseSensitive: false } // 低权重:列表(相似结构,辅助判断)
  ]);
}
4.2.3.2 结构特征检测

针对 Table 组件内部结构,定义特征、权重及期望得分区间,通过检测函数判断是否符合 Table 结构,核心代码如下:

typescript 复制代码
/**
 * 获取 Table 组件结构特征(用于补偿映射评分,判定是否为 Table )
 * @returns 结构特征数组(含检测方法、权重、期望得分区间)
 */
public static getStructureFeatures(): StructureFeature[] {
  return [
    {
      name: 'hasGridLayout',
      detector: (node: any) => this.detectGridLayout(node),
      weight: 0.9,
      expectedRange: [0.8, 1.0] // 核心特征,高权重(网格布局是 Table 关键)
    },
    {
      name: 'hasMultipleRows',
      detector: (node: any) => this.detectMultipleRows(node),
      weight: 0.8,
      expectedRange: [0.8, 1.0] // 高权重: Table 需多行列结构
    },
    {
      name: 'hasTableRows',
      detector: (node: any) => this.detectTableRows(node),
      weight: 0.8,
      expectedRange: [0.7, 1.0] // 高权重:存在 Table 行结构
    },
    {
      name: 'hasUniformColumns',
      detector: (node: any) => this.detectUniformColumns(node),
      weight: 0.7,
      expectedRange: [0.7, 1.0] // 中高权重:列宽统一( Table 特征)
    },
    {
      name: 'hasTableHeaders',
      detector: (node: any) => this.detectTableHeaders(node),
      weight: 0.7,
      expectedRange: [0.6, 1.0] // 中高权重:存在表头( Table 核心特征)
    },
    {
      name: 'hasPagination',
      detector: (node: any) => this.detectPagination(node),
      weight: 0.6,
      expectedRange: [0.5, 1.0] // 低权重:分页(辅助判断,非必需)
    }
  ];
}

以网格布局检测 detectGridLayout 为例,通过分析子元素 X 、 Y 轴分布判断是否形成规则网格,核心实现如下:

typescript 复制代码
/**
 * 检测节点是否具有 Table 网格布局( Table 核心结构特征)
 * @param node Figma 节点(待检测节点)
 * @returns 匹配度( 0-1 ,≥ 0.6 判定为符合 Table 网格特征)
 */
private static detectGridLayout(node: any): number {
  // 节点子元素不足 4 个,直接判定非网格( Table 至少 2 行 2 列)
  if (!node.children || node.children.length < 4) return 0;
  // 过滤无效子元素(无绝对坐标的节点排除)
  const validChildNodes = node.children.filter((child: any) => child.absoluteBoundingBox);
  if (validChildNodes.length < 4) return 0;
  
  // 坐标分组精度因子(取整减少微小偏差,避免因坐标误差误判)
  const coordPrecisionFactor = 10;
  const rowGroups = new Map<number, any[]>(); // Y 轴分组(对应 Table 行)
  const colGroups = new Map<number, any[]>(); // X 轴分组(对应 Table 列)
  
  // 按坐标分组(取整后分组,减少精度误差)
  validChildNodes.forEach(child => {
    const rowKey = Math.round(child.absoluteBoundingBox.y / coordPrecisionFactor) * coordPrecisionFactor;
    const colKey = Math.round(child.absoluteBoundingBox.x / coordPrecisionFactor) * coordPrecisionFactor;
    rowGroups.set(rowKey, [...(rowGroups.get(rowKey) || []), child]);
    colGroups.set(colKey, [...(colGroups.get(colKey) || []), child]);
  });
  
  const rowCount = rowGroups.size; // 行数
  const colCount = colGroups.size; // 列数
  
  // 行/列数不足 2 ,不符合 Table 网格结构
  if (rowCount < 2 || colCount < 2) return 0;
  
  // 计算网格规则度(实际单元格数与理论数的偏差,越接近 1 越规则)
  const theoreticalCellCount = rowCount * colCount; // 理论单元格数
  const actualCellCount = validChildNodes.length; // 实际子元素数(单元格)
  const gridRegularity = 1 - Math.abs(actualCellCount - theoreticalCellCount) / theoreticalCellCount;
  
  return Math.max(0, gridRegularity); // 确保匹配度非负
}
4.2.3.3 几何特征

行模式
列模式
是(相似度≥ 0.6 )
否(相似度< 0.6 )
提取 Figma 节点( Text/Shape/Frame )
获取节点 absoluteBoundingBox 坐标
投影至画布坐标系,生成散点
应用聚类算法,按坐标相似度分组
识别行列模式
相同 Y 范围节点归为一行,验证多行列数是否相等
相同 X 范围节点归为一列,验证多列行数是否相等
符合 Table 特征?
判定为 Table 组件
不判定为 Table 组件

行模式检测核心实现代码如下:

typescript 复制代码
/**
 * 检测 Table 行模式(按 Y 坐标聚类判定,核心判定逻辑)
 * @param nodes 几何节点数组( Text/Shape/Frame 类型)
 * @param originalNode 原始 Figma 节点(待检测父节点)
 * @param config 聚类配置(自定义聚类参数)
 * @returns 表格模式( null 表示非行模式,不满足 Table 特征)
 */
private detectRowPattern(
  nodes: GeometricNode[], 
  originalNode: any,
  config: ClusteringConfig
): TablePattern | null {
  // 坐标分组精度因子(控制分组粒度,避免微小偏差影响判定)
  const coordGroupFactor = 100;
  
  // 按 Y 坐标分组,计算行数(相同 Y 范围归为一行)
  const rowCoordGroups = new Set(
    nodes.map(node => Math.round(node.bounds.y / coordGroupFactor) * coordGroupFactor)
  );
  const rowCount = Math.max(rowCoordGroups.size, 1); // 确保行数不小于 1
  
  // 行数不足 2 ,直接判定非行模式( Table 至少 2 行)
  if (rowCount < 2) return null;
  
  // 按 X 坐标分组,计算列数(相同 X 范围归为一列)
  const colCoordGroups = new Set(
    nodes.map(node => Math.round(node.bounds.x / coordGroupFactor) * coordGroupFactor)
  );
  const columnCount = Math.max(colCoordGroups.size, 1); // 确保列数不小于 1
  
  // 返回行模式判定结果(含行数、列数、布局类型、置信度)
  return {
    rowCount,
    columnCount,
    layoutType: this.determineLayoutTypeFromFigma(originalNode), // 从 Figma 获取原始布局类型
    nodes,
    confidence: this.calculateSimpleConfidence(rowCount, columnCount, nodes.length) // 计算匹配置信度
  };
}

4.3 布局与样式

Figma to Code 支持 Flex 布局和绝对定位布局,布局类型通过节点位置关系判定。

核心逻辑:水平交叠按行分组、垂直交叠按列分组,结合分组统计结果确定布局及方向,具体步骤如下:

  1. 按行分组,计算分组元素数量的均值和方差;
  2. 按列分组,计算分组元素数量的均值和方差;
  3. 按均值(越小越优)和方差(越小越优)判定分组方式:列分组对应 Flex 方向 'row',行分组对应 Flex 方向 'column',分组元素数> 1 时自动创建父容器;
  4. 对单层子图层递归执行上述步骤,完成全节点布局判定。

节点关系处理及投影示意如下:
节点关系判定
二维空间投影
二维空间投影
节点集合 A,B,C,D
包含/覆盖/相离
横向
纵向

4.3.1 绝对定位判断

同一层级两图层相互遮挡时,会创建 Wrapper 容器,内部采用绝对定位布局。

满足以下任一条件,即可判定为绝对定位,具体逻辑及代码实现如下:

条件 1: 是否设置绝对定位

检查节点是否存在 layoutPositioning 属性,若值为 "ABSOLUTE",直接判定为绝对定位:

typescript 复制代码
// 条件 1:节点自身设置绝对定位,直接判定(优先级最高)
// layoutPositioning 为 ABSOLUTE 是 Figma 节点绝对定位的直接标识
if (node.layoutPositioning === 'ABSOLUTE') {
  return true; // 启用绝对定位布局
}
条件 2: 根据父节点布局模式判断

父节点无有效 Auto Layout 时,子节点需采用绝对定位,判定逻辑如下:

typescript 复制代码
// 条件 2:根据父节点布局模式判定绝对定位(间接判定逻辑)
if (node.parent) {
  // 情况 A:父节点 layoutMode 为 NONE → 未启用 Auto Layout,子节点需手动定位
  if (node.parent.layoutMode === 'NONE') {
    return true; // 子节点采用绝对定位
  }
  // 情况 B:父节点无 layoutMode 属性(如 Group 类型)→ 不支持 Auto Layout
  if (!node.parent.layoutMode) {
    return true; // 子节点采用绝对定位
  }
}
绝对定位位置计算

判定为绝对定位后,通过 getCommonPositionValue 函数计算节点位置,适配不同父节点类型,核心逻辑如下:

typescript 复制代码
/**
 * 计算绝对定位节点的相对位置(适配不同父节点类型,避免定位偏差)
 * @param targetNode 目标绝对定位节点
 * @param config 配置项(可选,含嵌入矢量相关设置)
 * @returns 节点相对父容器的坐标(x,y),用于绝对定位赋值
 */
function getCommonPositionValue(targetNode: any, config?: any) {
  // 1. 常规场景:父节点存在且有绝对边界框(最常用场景)
  if (targetNode.parent && 'absoluteBoundingBox' in targetNode.parent && targetNode.parent.absoluteBoundingBox) {
    // 特殊场景:嵌入矢量图,需计算绝对位置偏移(消除父容器偏移影响)
    if (config?.embedVectors && 'svg' in targetNode && targetNode.svg) {
      return {
        x: (targetNode as any).absoluteBoundingBox.x - targetNode.parent.absoluteBoundingBox.x,
        y: (targetNode as any).absoluteBoundingBox.y - targetNode.parent.absoluteBoundingBox.y,
      };
    }
    // 常规场景:直接使用节点自身相对父容器的坐标
    return { x: targetNode.x, y: targetNode.y };
  }
  // 2. 特殊场景:父节点为 Group 类型 → 需消除 Group 自身坐标偏移
  if (targetNode.parent && targetNode.parent.type === "GROUP") {
    return {
      x: targetNode.x - targetNode.parent.x,
      y: targetNode.y - targetNode.parent.y,
    };
  }
  // 3. 默认场景:无父节点/特殊节点 → 返回自身绝对坐标(兜底逻辑)
  return { x: targetNode.x, y: targetNode.y };
}

4.3.2 Flex 布局

当 Figma 图层启用 Auto Layout 时,D2C 转换将采用 Flex 布局,使 UI 具备基础响应式能力。

同一层级元素的 Flex 布局分组思路:

  1. 优先判断子元素间是否遮挡,若遮挡则创建父容器包裹;
  2. 对无遮挡元素,按行、列分组后结合均值和方差,确定最优分组及 Flex 方向。

4.3.3 关于样式

Figma 与 Web 渲染引擎存在差异,典型场景为 "Figma 中单个 TEXT 节点可设置多种文本颜色"。对此,D2C 转换在检测到含多段不同样式时,会自动拆分节点为多个 <span> 标签,保证样式还原。

原始 Figma TEXT 节点树:

typescript 复制代码
{
  "type": "TEXT", // 节点类型:文本节点
  "characters": "Name: Tom", // 文本节点完整内容
  "styledTextSegments": [ // 多段样式文本集合(对应不同文本样式)
    {
      "characters": "Name: ", // 第一段文本内容
      "fills": [{ 
        "type": "SOLID", // 填充类型:纯色
        "color": { "r": 0.62, "g": 0.65, "b": 0.68 } // 对应十六进制 #9FC4D0
      }],
      "fontSize": 14 
    },
    {
      "characters": "Tom", // 第二段文本内容(与第一段样式不同)
      "fills": [{ 
        "type": "SOLID", 
        "color": { "r": 0.23, "g": 0.26, "b": 0.30 } // 对应十六进制 #3B434D
      }],
      "fontSize": 14 
    }
  ]
}

D2C 转码后(拆分多 span 标签,匹配原样式):

xml 复制代码
<span style="color: #9FC4D0">Name: </span>
<span style="color: #3B434D">Tom</span>

4.4 中间态代码

D2C 转换中,会先将 Figma 节点数据转为中间态抽象语法树( AST ),再生成最终代码。核心包含 AST Nodes 和 AST Builder,转换逻辑及示例如下:
AST 转换核心
AST 节点层
导入声明

ImportDeclaration
函数声明

FunctionDeclaration
JSX 元素节点

JSXElement
JSX 属性节点

JSXAttribute
AST 构建器
导入语句构建器

Import AST Builder
组件节点构建器

Component AST Builder
JSX 结构构建器

JSX AST Builder
属性节点构建器

Props AST Builder
JSON 数据源
代码生成器

Code Generate
目标代码文件

TSX File

核心概念

  • AST Nodes(静态数据结构):定义面向代码生成的静态语法树结构,规范数据格式;
  • AST Builder(语法树构建器):负责将 Figma 原始数据转换为结构化 AST 节点。

转换示例

typescript 复制代码
// 输入:Figma 原始节点 JSON 数据(以 FRAME 类型的 Button 组件为例)
const figmaFrameNodeData = {
  type: 'FRAME', // 节点类型:容器帧
  name: 'Button', // 节点名称(与组件名称对应)
  metaData: { componentName: 'Button' }, // 组件元数据:关联研发侧 Button 组件
  resolvedProps: { title: 'Click me', size: 16 }, // 随机新增数值属性 size,变更属性组合
  children: [] // 子节点集合
};

// 输出:结构化 AST 节点(适配 JSX 代码生成,与输入节点一一对应)
const jsxAstNode = {
  type: 'JSXElement', // AST 节点类型:JSX 元素(对应 React 组件)
  tagName: 'Button', // 标签名:与研发侧组件名称一致
  attributes: [
    { 
      type: 'JSXAttribute', 
      name: 'title', // 属性名:按钮文本属性
      value: 'Click me', // 属性值:按钮显示文本
      valueType: 'string' // 属性类型:字符串
    },
    { 
      type: 'JSXAttribute', 
      name: 'size', // 新增属性:对应输入新增的数值属性
      value: 16, // 随机数值,贴合按钮尺寸规范
      valueType: 'number' // 属性类型:数字
    }
  ],
  children: [] // 子 AST 节点(与输入节点 children 对应)
};

4.5 AI 优化

D2C 工程侧可生成高确定性代码,但存在样式冗余、结构不规范等问题,需借助 AI 泛化能力优化,核心解决"模型幻觉不确定性"与"生产级代码确定性"的平衡,同时实现代码标准化。

4.5.1 工程侧预处理

生产级代码对准确性、可控性要求极高,单靠 AI 无法保证,工程侧的节点清洗、组件映射等操作,本质是生成高确定性节点树,为 AI 优化提供可靠输入。对抗模型幻觉主要有两种方式:

1. 视觉稿协议的工程预处理

通过工程手段优化 Figma 设计稿,减少模型输入干扰,增强确定性:

  • 识别可映射至前端组件的图层,清理无效图层(如隐藏、空图层);
  • 识别可转为图片的图层组;
  • 识别 icon 组件,统一映射至研发侧图标库。
2. 结构化 JSON 转换

从 Figma 图层到代码生成,全程采用 JSON 结构化转换,约束模型输出、减少幻觉,核心优势:

  • 格式统一:固定结构,便于后续处理消费;
  • 减少幻觉:固定格式约束模型,避免编造无关内容;
  • 关系清晰:嵌套结构体现数据层级关联;
  • 类型明确:字段类型清晰,可直接用于应用程序。

4.5.2 Agenct 侧 AI 辅助代码标准化

工程侧生成的代码存在内联样式、重复样式、组件庞大等问题,传统工程化难以解决,需借助 AI 泛化能力重构优化,实现代码标准化。

工程侧原始代码(存在问题)
typescript 复制代码
import React from 'react';
import { Modal } from 'ssc-ui-react';
// 问题:内联样式冗余、未拆分组件、无类型定义(优化前)
const ConfirmModalComponent = () => {
  // 随机变更数值:模态框宽度控制变量
  const modalWidth = 520;
  return (
    <Modal 
      data-layer="dialog" 
      title="Confirm" 
      okText="Confirm" 
      cancelText="Cancel"
      width={modalWidth} // 引用随机数值变量
    >
     <div
        data-layer="modal-content"
        style={{ display: "flex", justifyContent: "flex-start", alignItems: "flex-start", padding: 18 }}
      >
        <div
          data-layer="please-notice-that-a"
          style={{ justifyContent: "flex-start",
            alignItems: "flex-start",
            whiteSpace: "pre-wrap",
            wordWrap: "break-word",
            overflowWrap: "break-word",
            fontSize: 15
          }}
        >Are you sure you want to submit the request?</div>
      </div>
    </Modal>
  );
};
export default ConfirmModalComponent;
4.5.2.1 提示词工程(核心优化手段)

采用 In-Context-Learning 范式,将复杂优化任务拆分为聚焦子任务,通过精准提示词引导模型完成标准化重构,提示词如下:

bash 复制代码
# React 组件优化专家 - 标准化重构指南
## 核心定位
资深 React 开发专家,精通现代 Web 开发、组件设计、Hooks 封装与前端工程化最佳实践,专注**React 组件架构重构、性能优化、代码规范化**。
---
## 一、标准化分析思维链(按步骤拆解优化任务,降低复杂度)
### 第一步:代码结构分析
1. 职责识别:明确组件核心功能定位(避免功能耦合)
2. 问题检测:组件体积超标、冗余代码、内联样式滥用、TS 类型缺失、违反单一职责
### 第二步:样式优化分析
1. 问题识别:冗余默认样式(如 width:auto)、无效字体样式、内联样式未抽离
2. 优化策略:清理无效样式、内联样式迁移至 LESS、抽离可复用样式类
### 第三步:组件拆分策略
1. 拆分原则:按功能职责/UI 区域/数据流拆分(遵循单一职责)
2. 标准目录结构(前端工程化规范,统一项目结构):
	├── api/           # 接口请求、Mock 数据(数据请求层)
	├── types/         # 数据模型、类型定义(TS 类型层)
	├── const/         # 常量、枚举(常量管理)
	├── hooks/         # 自定义 Hooks(状态逻辑层)
	├── components/    # 单一职责子组件(UI 组件层)
	│   ├── child-component/
	│   │   ├── index.ts       # 导出入口(统一导出,简化引用)
	│   │   ├── child-component.tsx # 组件逻辑(核心 UI 与逻辑)
	│   │   └── styles.less    # 组件样式(样式隔离)
	├── index.tsx      # 页面主入口(组件对外暴露)
	└── styles.less    # 全局样式(公共样式管理)
### 第四步:类型系统设计(TS 类型安全,避免 any 隐患)
1. 核心定义:组件 Props、数据结构、事件函数类型(全量覆盖)
2. 安全规范:禁用 any;明确函数参数/返回值;复用 TS 内置工具类型(如 Partial、Pick)
### 第五步:状态管理优化(按状态类型选型,降低维护成本)
1. 需求划分:内部状态、跨组件状态、异步数据状态
2. 方案选型:自定义 Hooks 管理复杂状态;Context 管理全局状态
---
## 二、强制优化规范(严格执行,保证代码统一性)
1. 样式规范:移除冗余样式、用 CSS 变量统一样式、内联样式全迁移至 LESS、封装可复用样式类
2. 组件规范:遵循单一职责、按标准目录组织、kebab-case 命名、子组件标配入口+逻辑+样式
3. 类型规范:全量定义 TS 接口、禁用 any、保证全链路类型安全
4. 代码质量规范:遵循 DRY(无重复)、KISS(简洁)、SOLID 原则、补充必要注释
---
## 三、优化示例(直观对比,明确优化方向)
### 优化前(耦合巨型组件)
const ProTable = () => {
  // 200+ 行代码,耦合多模块功能(表格渲染、筛选、分页等)
};
### 优化后(解耦轻量化组件)
const ProTable = () => {
  return (
    <TabBar items={TAB_ITEMS} />
    <ProTable {...tableConfig} />
  );
};
AI 优化后代码结构

经提示词引导,AI 会对原始代码进行标准化重构,核心优化点可视化示意如下:
组件根目录
index.tsx(主入口)
styles.less(全局样式)
components/(子组件目录)
modal-content/(模态框内容子组件)
index.ts(子组件导出)
modal-content.tsx(子组件逻辑)
styles.less(子组件样式)
types/(类型定义目录)
modal.types.ts(模态框相关类型)
hooks/(自定义 Hooks 目录)
useModal.ts(模态框相关 Hooks)

核心优化点:抽离内联样式至 LESS 文件、拆分单一职责子组件、补充 TS 类型定义、按标准目录组织代码,提升可维护性和可读性。

五、附录

相关推荐
敲代码的鱼哇2 小时前
发送短信/拨打电话/获取联系人能力 UTS 插件(cz-sms)
android·前端·ios·uni-app·安卓·harmonyos·鸿蒙
smallcelebration2 小时前
130 保姆级 配置mcp+figma+cursor 通过对话直接生成设计稿
figma
搬搬砖得了2 小时前
Vue 响应式对象异步赋值作为 Props:二次渲染问题与组件设计哲学
前端·vue.js
带娃的IT创业者2 小时前
Claude Code Routines 深度解析:重新定义 AI 辅助编程的工作流自动化
运维·人工智能·自动化·ai编程·工作流·anthropic·claude code
张西餐2 小时前
Promise的理解
前端
wsjsf2 小时前
智能代码审查助手的搭建
java·学习·ai编程
天渺工作室2 小时前
别再写改名脚本了,一个 Vite 插件搞定压缩、校验、自动哈希命名vite-plugin-pack-orchestrator
前端·vite
大龄程序员狗哥3 小时前
第30篇:使用Flask部署你的第一个AI模型——打造简易Web API(项目实战)
前端·人工智能·flask
sunneo3 小时前
专栏A-AI原生产品设计-06-AI原生产品的未来展望(专栏A终篇)
人工智能·产品运营·产品经理·ai编程·ai-native