Figma 插件开发指南
基于官方文档和实践总结的 Figma 插件开发流程。
参考资料
| 文档 | 链接 |
|---|---|
| 插件开发主站 | https://developers.figma.com/ |
| Manifest 规范 | https://www.figma.com/plugin-docs/manifest/ |
| editorType 说明 | https://www.figma.com/plugin-docs/setting-editor-type/ |
| 插件 API 参考 | https://www.figma.com/plugin-docs/api/figma/ |
| showUI 详细文档 | https://developers.figma.com/docs/plugins/api/properties/figma-showui/ |
| figma.ui API | https://developers.figma.com/docs/plugins/api/figma-ui/ |
| TextNode API | https://developers.figma.com/docs/plugins/api/TextNode/ |
项目结构
Figma 插件至少需要三个文件:
my-plugin/
├── manifest.json # 插件配置
├── code.ts # 主逻辑(TypeScript 源码)
├── code.js # 编译后的主逻辑(Figma 实际加载)
└── ui.html # 插件 UI 弹窗(可选)
manifest.json 核心字段
{
"name": "插件名称", // 在菜单中显示的名称
"id": "插件ID", // Figma 分配的插件 ID
"api": "1.0.0", // API 版本
"main": "code.js", // 主逻辑入口文件(相对路径)
"ui": "ui.html", // UI 文件(可选)
"editorType": ["figma"], // 支持的编辑器类型
"documentAccess": "dynamic-page" // 新插件建议开启
}
editorType 可选值
| 值 | 含义 |
|---|---|
"figma" |
Figma 设计模式 |
"figjam" |
FigJam 白板模式 |
"dev" |
Dev Mode |
"slides" |
Figma Slides |
"buzz" |
Figma Buzz |
注意:"figjam" 和 "dev" 不能同时使用。
其他常用可选字段
{
"networkAccess": {
"allowedDomains": ["none"], // 或具体域名
"devAllowedDomains": ["http://localhost:3000"] // 开发环境域名
},
"capabilities": ["codegen", "inspect"], // Dev Mode 能力
"permissions": ["currentuser"] // 需要用户数据的权限
}
TypeScript 编译配置
@figma/plugin-typings 包的 package.json 中 "main": "",导致 TypeScript 的 types 编译选项无法自动解析。需要手动添加引用:
tsconfig.json:
{
"compilerOptions": {
"target": "ES2017",
"module": "commonjs",
"lib": ["ES2017"],
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["code.ts"]
}
code.ts 顶部必须添加三斜线引用:
/// <reference path="./node_modules/@figma/plugin-typings/index.d.ts" />
否则会报 Cannot find name 'figma' 错误。
package.json:
{
"devDependencies": {
"@figma/plugin-typings": "^1.100.0",
"typescript": "^5.3.0"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"watch": "tsc -p tsconfig.json --watch"
}
}
核心 API
显示 UI 弹窗
figma.showUI(__html__, {
width: 360, // 宽度,默认 300,最小 70
height: 200, // 高度,默认 200,最小 0
title: '标题', // 窗口标题
visible: true, // 是否显示,默认 true
themeColors: false // 是否启用明暗主题 CSS 变量
});
__html__是全局变量,指向 manifest.json 中ui字段指定的 HTML 文件内容figma.ui.hide()/figma.ui.show()控制显示隐藏figma.ui.resize(w, h)动态调整大小figma.ui.close()销毁 UI
主线程与 UI 通信
主线程接收消息:
figma.ui.onmessage = (msg: { type: string }) => {
if (msg.type === 'some-action') {
// 处理消息
}
};
UI 发送消息给主线程:
parent.postMessage({ pluginMessage: { type: 'some-action' } }, '*');
创建文字节点
// 1. 必须先加载字体(修改 textNode 的任何渲染属性前必须加载)
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
// 2. 创建文字节点
const textNode = figma.createText();
// 3. 设置属性(字体已加载后才能设置)
textNode.characters = 'Hello';
textNode.fontSize = 50;
textNode.fontName = { family: 'Inter', style: 'Regular' };
// 4. 添加到页面
figma.currentPage.appendChild(textNode);
// 5. 定位
textNode.x = 100;
textNode.y = 200;
// 6. 选中
figma.currentPage.selection = [textNode];
关键约束: 在修改 characters、fontSize、fontName 等会触发文字重新渲染的属性之前,必须先调用 figma.loadFontAsync() 加载对应字体。
获取可用字体
// 列出所有可用字体
const fonts = await figma.listAvailableFontsAsync();
// 使用第一个可用字体
if (fonts.length > 0) {
await figma.loadFontAsync({
family: fonts[0].fontName.family,
style: fonts[0].fontName.style,
});
}
TextNode 常用属性
| 属性 | 类型 | 说明 |
|---|---|---|
characters |
string |
文字内容 |
fontSize |
number |
字体大小,最小 1 |
fontName |
{ family: string, style: string } |
字体名称和样式 |
textAlignHorizontal |
'LEFT' \| 'CENTER' \| 'RIGHT' \| 'JUSTIFIED' |
水平对齐 |
textAlignVertical |
'TOP' \| 'CENTER' \| 'BOTTOM' |
垂直对齐 |
fills |
ReadonlyArray<Paint> |
填充(颜色等) |
letterSpacing |
LetterSpacing |
字符间距 |
lineHeight |
LineHeight |
行高 |
x, y |
number |
位置坐标 |
width, height |
number (只读) |
尺寸 |
文字范围操作
TextNode 支持按字符范围设置不同样式:
textNode.setRangeFontSize(0, 5, 24); // 前5个字符字体大小24
textNode.setRangeFontName(0, 5, { family: 'Inter', style: 'Bold' });
textNode.setRangeFills(0, 5, [{ type: 'SOLID', color: { r: 1, g: 0, b: 0 } }]);
其他常用 API
// 通知
figma.notify('操作成功');
figma.notify('操作失败', { error: true });
// 关闭插件
figma.closePlugin();
// 视口
figma.viewport.center; // { x: number, y: number }
// 当前页面
figma.currentPage; // PageNode
// 选区
figma.currentPage.selection; // readonly SceneNode[]
在 Figma 中加载插件
- 打开 Figma Desktop
- Plugins → Development → Import plugin from manifest...
- 选择
manifest.json文件 - 插件出现在 Plugins 菜单中,点击即可运行
常见问题
TypeScript 找不到 figma 全局变量
原因:@figma/plugin-typings 的 package.json 中 "main": "",TypeScript 无法自动解析。
解决:在 code.ts 顶部添加:
/// <reference path="./node_modules/@figma/plugin-typings/index.d.ts" />
修改文字属性报错
修改 characters、fontSize 等属性前必须加载字体:
await figma.loadFontAsync({ family: 'Inter', style: 'Regular' });
插件 UI 不显示
检查 manifest.json 中 ui 字段是否正确指向 HTML 文件,以及 HTML 文件是否存在。