这个插件是chrome 浏览器插件,而不是常规意义上的figma官方指定的插件。
作为前端同学,常规研发过程中;都是由UI同学出图,然后,FE开始像素级别的翻译。如果直接让设计稿转为代码。并附带相关的样式,那确实能为自己省好多的时间。由此开始做了这个插件,期望对大家有些启发 目前该插件已经实现如下功能;实现的功能如下:
- 快速生成复制选中节点的css文件
- 快速生成选择节点 React 组件
实现效果如下图:

后期计划实现:
- 直接将全部界面,智能化的划分组件,并生成相应的工程文件
- 一键部署,并能够快速的构建静态演示界面

开始介绍插件之前,先了解一些基础知识吧。
Figma的三种API的主要区别
figma 本身提供了三种实现APIs的方式;分别如下;简单做了一个对比表格;希望对大家有帮助 以下是Figma提供的三种API的对比表格,概述了它们的主要特点和区别:
特性/API类型 | 插件API (Plugin API) | 小部件API (Widget API) | REST API |
---|---|---|---|
功能 | 创建交互式体验,扩展Figma的功能。 | 创建自定义交互式画布节点,具有丰富的用户界面。 | 从自己的脚本、工具或应用程序中访问Figma文件。 |
适用场景 | 需要实时与Figma设计或FigJam文件交互的场景。 | 需要在画布上添加交互式元素,如实时投票、表情贴纸等。 | 需要在Figma之外自动化处理Figma文件的场景。 |
交互模型 | 在Figma和FigJam中,用户打开特定的设计或文件,插件在读或写文件时与用户互动。 | 在Figma和FigJam中,用户打开特定的设计或文件,小部件添加到画布上,对所有查看文件的人可见。 | 在任何自动化系统中,用户设置预编程的例行程序或脚本,之后按计划或事件触发运行。 |
优势 | - 实时更改Figma设计或FigJam文件内容。 - 允许编辑Figma设计或FigJam文件的几乎所有方面。 | - 直接在画布上创建丰富和交互式的多人体验。 | - 允许其他系统读取Figma设计和/或FigJam文件的内容,即使没有打开Figma。 - 更适合一次性访问单个文件中的大量节点或多个文件中的节点。 - 使用个人访问令牌调用API时,可以访问用户可以访问的所有文件。 |
限制 | - 只能读取和编辑用户在Figma中打开的当前文件。 - 除非用户手动在每个文件上触发插件或插件代码调用REST API,否则不能跨多个文件工作。 | - 只能读取和编辑用户在Figma中打开的当前文件。 - 不能跨多个文件工作;每个小部件实例仅作用于其插入的文件。 | - 主要是只读的,例外包括评论、评论反应和变量。 |
非官方APIs
通过阅读figma 开发者文档之后,发现在Figma的web端中,Figma 将相应的函数和方法都通过 figma 暴露在window之下:

因此我觉得做一个浏览器的插件,限制没有那么多,也方便安装使用,另外方便快速开发;验证自己的一些想法;我从开始想做,到做成MVP版本;仅仅花了3个小时;
实现过程记录
在开发浏览器插件的时候,使用 plasmo 可以方便快速构建一个简单应用。在这里强调一下,使用plasmo的时候请优先阅读一下他的使用文档,方便快速启动项目,docs.plasmo.com/framework
base
pnpm create plasmo --with-tailwindcss
基础工作这样就完成了,接下来。刚才已经提到了 window.figma 可以直接调用相关的方法,我重点用到了两个相关的钩子:
获取选中元素 currentPage 中的 selection
通过figma.currentPage.selection
方法,可以实现确定当前界面选中的元素。
js
const node = window.figma.currentPage.selection[0]

接下来关键的思路就是通过相应节点的css、树关联关系、可视化的图片给 gpt-4-vision-preview
模型。让模型根据相应的信息生成代码。
1. 获取选中元素的css
控制台显示选中节点的实例,通过实例是可以调用 getCSSAsync;获取相应的css。 下面有一个简单的示例;方便获取相应的css。
js
function nodeToCSS(name, css) {
return `.${name} {
${Object.keys(css).map(k => `${k}: ${css[k]};`).join('\n ')}
}`
}
const genCssCode = async () => {
const node = window?.figma?.currentPage.selection[0]
const css = await node.getCSSAsync()
// const cssString = JSON.stringify(css, null, 2);
const className = node.type === "TEXT" ? "text" : node.name
const formatCss = nodeToCSS(node.name, css)
console.log('formatCss:',css)
}

2. 获取相应的子节点
在选中的节点实例中,有一个 children 属性。可以获取这个节点相应的多级子节点。
ts
const generateTree = async (
node: SceneNode,
resolve?: (value: unknown) => void
): Promise<TypeNodeInfo> => {
// 获取相应的css。
const css = await node.getCSSAsync();
const cssString = JSON.stringify(css, null, 2);
const tree: TypeNodeInfo = {
name: node.name,
type: node.type,
css: cssString,
children: [],
};
if ('children' in node) {
for (const child of node.children) {
const childTree = await generateTree(child);
tree.children.push(childTree);
}
resolve?.(tree);
} else {
resolve?.(tree);
}
return tree;
}
3. 节点转化为图片
js
// 获取生成图片的base64
const image = await node.exportAsync({ format: "PNG" })
const base64 = arrayBufferToBase64(image)
相应的信息已经有了,接下来就是将相应的信息汇总成为比较合理的 prompt
即可。 其实到此,基础的就讲完了。 其实说的已经比较絮叨了,直接上代码链接吧。全部代码已经放在GitHub 需要的自取。
感想
研发一直就很卷;重复造轮子也是一直存在的;毕竟要展示自己或者团的技术实力。开发提效,一直是前端研发同学都在卷的一个方面。css框架、组件库、模板库、低代码、图标库...等等;都是希望快速完成页面的构建,从而能够早下班(目前看,可能是早被裁!)。