FEATURED · 精选文章

Figma 插件 API 模式速查:基于 figma-use skill 的程序化构图、自动布局与组件变体实战指南

发布时间 / 2026/9/13 4:02:23
来源 / 创域科博编辑部
栏目 / 资讯中心
Figma 插件 API 模式速查:基于 figma-use skill 的程序化构图、自动布局与组件变体实战指南 Figma 插件 API 模式速查基于 figma-use skill 的程序化构图、自动布局与组件变体实战指南【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills本指南围绕skills/.curated/figma-useskill 的核心参考文档 plugin-api-patterns.md 展开系统梳理通过use_figmaMCP 在 Figma 文件中执行 JavaScript 的常见 Plugin API 操作模式覆盖节点创建、填充描边、自动布局、效果、组件与变体、样式、查找与网格等完整能力面。读完你将掌握一套可直接复制运行的 API 代码模式并理解页面上下文、插件生命周期、布局顺序约束等最容易踩坑的底层规则能够独立编写脚本化建图、组装组件变体与设计系统。文档定位use_figma skill 的快速参考plugin-api-patterns.md是 use_figma skill 的配套快速参考文档定位是“常见 Figma 插件 API 操作速查”。在 skill 的参考文档体系中它与 gotchas.md常见坑与 WRONG/CORRECT 示例、common-patterns.md可直接套用的脚本骨架、api-reference.mdAPI 支持面总表相互补充文档何时加载覆盖内容gotchas.md任何use_figma调用前每个已知坑位及错误/正确代码示例common-patterns.md需要可直接运行的代码示例形状、文本、自动布局、变量、组件、多步工作流脚本骨架plugin-api-patterns.md本文主题创建/编辑节点填充、描边、自动布局、效果、分组、克隆、样式api-reference.md需要精确的 API 支持面节点创建、变量 API、核心属性、哪些可用哪些不可用此外完整的类型签名在 plugin-api-standalone.index.md11,292 行类型文件的索引与 plugin-api-standalone.d.ts全量类型文件按符号 grep 使用中它们是 API 表面的权威来源。执行基础Execution Basics页面上下文每次调用都会重置use_figma每次调用之间页面上下文会重置——figma.currentPage总是从第一个页面开始。因此每次调用开始时都必须用await figma.setCurrentPageAsync(page)切换到目标页面并加载其内容const targetPage figma.root.children.find(p p.name My Page); await figma.setCurrentPageAsync(targetPage); // targetPage.children is now populated这条规则在 SKILL.md 中被列为 Critical 规则同步 setterfigma.currentPage page在use_figma运行时会直接抛错必须使用异步方法。同时页面是按需增量加载的切换页面这个动作本身就负责把该页内容装载进内存。关闭插件每次执行必须显式结束文档强调每次执行必须在成功时调用figma.closePlugin()出错时调用figma.closePluginWithFailure()figma.closePlugin(Success message describing what was done); figma.closePluginWithFailure(Description of what went wrong);且figma.notify()不存在——所有信息都通过关闭消息字符串返回。这一点在 api-reference.md 的“What Does NOT Work”表和 gotchas.md 中都有明确证据figma.notify()会抛出not implementedfigma.showUI()、figma.openExternal()则是静默 no-op。需要说明的是在use_figma的 MCP 运行环境下脚本会被自动包进异步上下文return才是输出通道返回值自动 JSON 序列化closePlugin/closePluginWithFailure由运行时统一处理——这是 SKILL.md 与本文档表述差异的来源两者的共同底线是代码必须有明确的成功/失败结束路径不能挂起。增量工作一次只做一小步不要在一次调用里建完整块屏幕。把工作拆成小步骤创建 tokens/变量创建文本样式构建单个组件组合区块组装屏幕步骤之间用get_metadata验证结构每个重要创建里程碑后用get_screenshot尽早发现视觉问题。这与 validation-and-recovery.md 的推荐工作流一致get_metadata返回节点 ID、类型、名称、位置、尺寸的 XML 树用于验证结构/层级/数量/命名/定位快而便宜get_screenshot渲染像素级图像用于验证颜色、字体渲染、效果、变量模式解析慢且响应大只在关键里程碑调用。两者结合可以在错误扩散前止损。创建节点Creating Nodes帧Framesconst frame figma.createFrame(); frame.name Container; frame.resize(1440, 900); frame.x 0; frame.y 0; frame.fills [{ type: SOLID, color: { r: 0.98, g: 0.98, b: 0.99 } }];从源码结构看createFrame()返回FrameNode类型索引中对应DefaultFrameMixin它同时具备自动布局、裁剪与子节点能力。注意 gotchas.md 提醒直接 append 到页面的顶层节点默认落在 (0,0)会与既有内容重叠——应先扫描figma.currentPage.children找到最右节点的右边界再把新节点放到maxX 100处而嵌套在 frame/auto-layout 内的子节点由父级定位无需扫描。文本Text// MUST load font before any text operations await figma.loadFontAsync({ family: Inter, style: Regular }); const text figma.createText(); text.fontName { family: Inter, style: Regular }; text.fontSize 16; text.lineHeight { value: 24, unit: PIXELS }; text.letterSpacing { value: 0, unit: PERCENT }; text.characters Hello World; text.fills [{ type: SOLID, color: { r: 0.1, g: 0.1, b: 0.12 } }];文本操作有两条硬性前置规则见 SKILL.md 第 8、17 条字体必须先loadFontAsync加载所有 Promise含loadFontAsync、setCurrentPageAsync必须await否则会 fire-and-forget 造成静默失败或竞态。另外 gotchas.md 强调lineHeight与letterSpacing必须是{value, unit}对象而非裸数字字体风格名如SemiBoldvsSemi Bold因文件而异写脚本前最好用候选列表逐个 try 探测。矩形Rectanglesconst rect figma.createRectangle(); rect.name Background; rect.resize(400, 300); rect.cornerRadius 12; rect.fills [{ type: SOLID, color: { r: 0.95, g: 0.95, b: 0.96 } }];椭圆Ellipsesconst circle figma.createEllipse(); circle.name Avatar Circle; circle.resize(48, 48); circle.fills [{ type: SOLID, color: { r: 0.85, g: 0.87, b: 0.90 } }];线条Linesconst line figma.createLine(); line.name Divider; line.resize(400, 0); line.strokes [{ type: SOLID, color: { r: 0, g: 0, b: 0 }, opacity: 0.08 }]; line.strokeWeight 1;SVG 导入const svgString svg width24 height24 viewBox0 0 24 24 fillnone xmlnshttp://www.w3.org/2000/svg path dM5 12h14M12 5l7 7-7 7 strokeblack stroke-width2 stroke-linecapround stroke-linejoinround/ /svg; const node figma.createNodeFromSvg(svgString); node.name Icon/Arrow Right; node.resize(24, 24);createNodeFromSvg在类型索引中返回FrameNode是快速造图标/插图的常用手段component-patterns.md 中 INSTANCE_SWAP 模式正是先把 SVG 装进独立ComponentNode如Icon/Searchresize 24×24再作为可替换槽位使用。填充与描边Fills Strokes纯色填充Solid Fillnode.fills [{ type: SOLID, color: { r: 0.2, g: 0.2, b: 0.25 } }];带不透明度的填充node.fills [{ type: SOLID, color: { r: 0.2, g: 0.2, b: 0.25 }, opacity: 0.5 }];无填充透明node.fills [];线性渐变Linear Gradientnode.fills [{ type: GRADIENT_LINEAR, gradientStops: [ { color: { r: 0.2, g: 0.36, b: 0.96, a: 1 }, position: 0 }, { color: { r: 0.56, g: 0.24, b: 0.88, a: 1 }, position: 1 } ], gradientTransform: [[1, 0, 0], [0, 1, 0]] }];描边Strokesnode.strokes [{ type: SOLID, color: { r: 0.85, g: 0.85, b: 0.87 } }]; node.strokeWeight 1; node.strokeAlign INSIDE; // CENTER, OUTSIDE多层填充Layerednode.fills [ { type: SOLID, color: { r: 0.95, g: 0.95, b: 0.96 } }, { type: SOLID, color: { r: 0.2, g: 0.36, b: 0.96 }, opacity: 0.05 } ];关于填充/描边有三条底层事实均有 gotchas 源码证据颜色是 0–1 范围不是 0–255。{r: 255, g: 0, b: 0}会触发 ZeroToOne 校验错误{r: 1, g: 0, b: 0}才是红色。fills/strokes 是只读数组。原地修改node.fills[0].color ...无效必须JSON.parse(JSON.stringify(node.fills))克隆、修改、再整体重新赋值。paint 颜色是{r,g,b}而 COLOR 变量值是{r,g,b,a}alpha 映射到 paint opacity两者不要混淆。自动布局Auto Layout基础设置const frame figma.createFrame(); frame.layoutMode VERTICAL; // or HORIZONTAL frame.primaryAxisSizingMode AUTO; // Hug main axis frame.counterAxisSizingMode FIXED; // Fixed cross axis frame.resize(360, 1); // Width fixed, height auto frame.itemSpacing 16; // Gap between children frame.paddingTop 24; frame.paddingBottom 24; frame.paddingLeft 24; frame.paddingRight 24;顺序问题在这里非常关键gotchas.md 有多条专门条目resize()会把primaryAxisSizingMode/counterAxisSizingMode重置为FIXED。正确顺序是先resize(300, 10)定初始尺寸再设 sizing mode否则高度会永远钉死在 10px。对应的现代写法是layoutSizingHorizontal/Vertical FIXED | HUG | FILL。对齐Alignment// Main axis (direction of layout) frame.primaryAxisAlignItems MIN; // Start frame.primaryAxisAlignItems CENTER; // Center frame.primaryAxisAlignItems MAX; // End frame.primaryAxisAlignItems SPACE_BETWEEN; // Distribute // Cross axis frame.counterAxisAlignItems MIN; // Start frame.counterAxisAlignItems CENTER; // Center frame.counterAxisAlignItems MAX; // End // NOTE: STRETCH is NOT valid — use MIN child.layoutSizingX FILLcounterAxisAlignItems不支持STRETCH会报Invalid enum value. Expected MIN | MAX | CENTER | BASELINE要达到“拉伸”效果父级用MIN子级在交叉轴上设FILL垂直布局设layoutSizingHorizontal FILL水平布局设layoutSizingVertical FILL。子节点尺寸Child Sizing// IMPORTANT: FILL can only be set AFTER the child is appended to an auto-layout parent parent.appendChild(child) child.layoutSizingHorizontal FILL; // Stretch to parent child.layoutSizingHorizontal HUG; // Shrink to content child.layoutSizingHorizontal FIXED; // Manual width child.layoutSizingVertical FILL; child.layoutSizingVertical HUG; child.layoutSizingVertical FIXED;FILL/HUG的顺序规则是 SKILL.md 第 12 条 Critical 规则layoutSizingHorizontal/Vertical FILL必须在parent.appendChild(child)之后设置先设再 append 会抛FILL can only be set on children of auto-layout frames。还有两个相关的经典坑HUG 父级会压扁 FILL 子级父级是HUG时FILL子级坍缩到最小尺寸。父级必须是FIXED或FILLFILL 子级才有空间扩展。这是 select 输入框、action row 文本被截断的常见原因。layoutGrow与 HUG 父级叠加会压缩内容父级primaryAxisSizingModeAUTO时给子级layoutGrow 1会让子级缩到自然尺寸以下应先把父级设为FIXED再 resize 出富余空间layoutGrow才正确填充。换行类网格布局Wrappingframe.layoutMode HORIZONTAL; frame.layoutWrap WRAP; frame.itemSpacing 24; // Horizontal gap frame.counterAxisSpacing 24; // Vertical gap (between rows)自动布局内的绝对定位child.layoutPositioning ABSOLUTE; child.constraints { horizontal: MAX, vertical: MIN }; // Top-right child.x parentWidth - childWidth - 8; child.y 8;效果Effects投影Drop Shadownode.effects [{ type: DROP_SHADOW, color: { r: 0, g: 0, b: 0, a: 0.08 }, offset: { x: 0, y: 4 }, radius: 16, spread: -2, visible: true, blendMode: NORMAL }];内阴影Inner Shadownode.effects [{ type: INNER_SHADOW, color: { r: 0, g: 0, b: 0, a: 0.05 }, offset: { x: 0, y: 1 }, radius: 2, spread: 0, visible: true, blendMode: NORMAL }];背景模糊Background Blurnode.effects [{ type: BACKGROUND_BLUR, radius: 16, visible: true }];图层模糊Layer Blurnode.effects [{ type: LAYER_BLUR, radius: 8, visible: true }];多重效果node.effects [ { type: DROP_SHADOW, color: { r: 0, g: 0, b: 0, a: 0.04 }, offset: { x: 0, y: 1 }, radius: 3, spread: 0, visible: true, blendMode: NORMAL }, { type: DROP_SHADOW, color: { r: 0, g: 0, b: 0, a: 0.06 }, offset: { x: 0, y: 8 }, radius: 24, spread: -4, visible: true, blendMode: NORMAL } ];进阶提示来自 api-reference.md如果要把效果与变量绑定需用figma.variables.setBoundVariableForEffect(effect, field, variable)——阴影支持colorCOLOR与radius | spread | offsetX | offsetYFLOAT模糊支持radiusFLOAT该函数返回新的 effect 对象必须捕获并重新赋值给node.effects。不透明度与混合模式Opacity Blend Modesnode.opacity 0.5; node.blendMode NORMAL; // MULTIPLY, SCREEN, OVERLAY, DARKEN, LIGHTEN, etc.圆角与裁剪Corner Radius Clipping// Uniform node.cornerRadius 12; // Per-corner node.topLeftRadius 12; node.topRightRadius 12; node.bottomLeftRadius 0; node.bottomRightRadius 0;从类型索引看cornerRadius/cornerSmoothing来自CornerMixin逐角圆角来自RectangleCornerMixin。若要将圆角绑定到变量api-reference.md 明确要求用四个独立角而不是cornerRadiussetBoundVariable(topLeftRadius | topRightRadius | bottomLeftRadius | bottomRightRadius, variable)。frame.clipsContent true; // Children clipped to frame bounds分组与组织Grouping Organization组Groupsconst group figma.group([node1, node2, node3], figma.currentPage); group.name Grouped Elements;区块Sectionsconst section figma.createSection(); section.name My Section; section.resizeWithoutConstraints(800, 600); section.x 0; section.y 0; // IMPORTANT: Sections dont auto-resize — always resize after adding content区块不会随内容自动调整尺寸gotchas.md 有专门条目append 内容后必须显式section.resizeWithoutConstraints(Math.max(child.width 100, 800), Math.max(child.height 100, 600))否则节点会溢出区块边界。另外 reparent 不会重置位置——appendChild到新父级后要显式重设 x/y。追加子节点parentFrame.appendChild(childNode); // Insert at a specific index parentFrame.insertChild(0, childNode); // Insert at beginning组件与变体Components Variants创建组件const component figma.createComponent(); component.name Button/Primary; component.description Primary action button.;createComponent()返回ComponentNode行为类似FrameNode但可发布、可实例化、可组合成变体集合component-patterns.md。创建实例const instance component.createInstance(); instance.x 200; instance.y 100;按 Key 导入组件团队库以下方法从团队库非当前文件导入组件。当前文件内的组件用figma.getNodeByIdAsync()或findOne()/findAll()直接定位。// Import a published component from a team library by its key const comp await figma.importComponentByKeyAsync(componentKey) const instance comp.createInstance() // Import a published component set from a team library by its key const set await figma.importComponentSetByKeyAsync(componentSetKey) const variant set.defaultVariant const variantInstance variant.createInstance()补充模式来自 common-patterns.md从组件集导入后可按sizemd等变体名过滤子组件compSet.children.find(c c.type COMPONENT c.name.includes(sizemd)) || compSet.defaultVariant实例还可以用instance.setProperties({ variant: primary, size: medium })切换变体属性。组合为变体Combine as Variants// IMPORTANT: Pass ComponentNodes (not frames) const componentSet figma.combineAsVariants( [variantA, variantB, variantC], figma.currentPage ); componentSet.name Button; componentSet.description Button component with multiple variants.; // CRITICAL: Layout variants in a grid after combining (they stack at 0,0) let maxX 0, maxY 0; componentSet.children.forEach((child, i) { child.x (i % numCols) * colWidth; child.y Math.floor(i / numCols) * rowHeight; }); for (const child of componentSet.children) { maxX Math.max(maxX, child.x child.width); maxY Math.max(maxY, child.y child.height); } componentSet.resizeWithoutConstraints(maxX 40, maxY 40);关于combineAsVariants有三条硬约束均有 gotchas 证据必须传ComponentNode传 frame 会直接抛错。headless 模式下它不会自动布局——所有变体叠在 (0,0)组件集表现为单个坍缩元素必须手动按网格排布。组件集尺寸必须从子节点实际边界计算maxX 40用公式推算容易让变体超出边界。变体命名用PropertyValue格式如sizemd, styleprimary每个唯一组合必须存在对应子组件缺失会在变体选择器里显示空档创建前先检查文件内已有命名惯例并保持一致。多轴变体size × style × state可按子组件名解析网格坐标Object.fromEntries(child.name.split(, ).map(p p.split()))得到{size, style}后映射到行列。组件属性Component Properties// addComponentProperty returns a STRING key — capture it! const labelKey component.addComponentProperty(label, TEXT, Button); const showIconKey component.addComponentProperty(showIcon, BOOLEAN, true); const iconSlotKey component.addComponentProperty(iconSlot, INSTANCE_SWAP, defaultIconId); // MUST link properties to child nodes via componentPropertyReferences labelNode.componentPropertyReferences { characters: labelKey }; iconInstance.componentPropertyReferences { visible: showIconKey, mainComponent: iconSlotKey };gotchas.md 用整节强调addComponentProperty返回的是字符串 key如label#4:0后缀不可预测绝不能硬编码或猜测也不能把返回值当对象取Object.keys那是字符串下标必然出错。component-patterns.md 补充了三点关键时机组件属性要在每个变体组件上、combineAsVariants之前添加组合后组件集自动继承不要直接在ComponentSetNode上加属性。只加属性而不链接到子节点等于没做——必须通过componentPropertyReferences绑定characters链接 TEXT 属性到 TextNodevisible链接 BOOLEAN 属性mainComponent链接 INSTANCE_SWAP 属性到 InstanceNode。INSTANCE_SWAP 是避免“变体爆炸”的关键模式当组件有大量可替换子元素如 30 个图标时绝不要为每个子元素建变体而应建一个独立的图标 ComponentNode再用单个 INSTANCE_SWAP 属性让使用者按需选择。样式Styles文本样式Text Styleawait figma.loadFontAsync({ family: Inter, style: Regular }); const style figma.createTextStyle(); style.name Body/Default; style.fontName { family: Inter, style: Regular }; style.fontSize 16; style.lineHeight { value: 24, unit: PIXELS }; style.letterSpacing { value: 0, unit: PERCENT }; // Apply to a text node textNode.textStyleId style.id;效果样式Effect Styleconst shadowStyle figma.createEffectStyle(); shadowStyle.name Shadow/Subtle; shadowStyle.effects [{ type: DROP_SHADOW, color: { r: 0, g: 0, b: 0, a: 0.06 }, offset: { x: 0, y: 2 }, radius: 8, spread: 0, visible: true, blendMode: NORMAL }]; // Apply to a node frame.effectStyleId shadowStyle.id;样式相关有两个 headless 环境的坑gotchas 证据TextStyle.setBoundVariable在 headless 下不可用它在类型 API 里存在但通过use_figma运行时调用会抛not a function。headless 下用原始值创建样式需要实时变量绑定时再在 Figma 样式面板交互完成。节点级node.setBoundVariable(...)和 paint 级figma.variables.setBoundVariableForPaint(...)在 headless 下仍正常。团队库样式按 key 导入figma.importStyleByKeyAsync(STYLE_KEY)后用node.setFillStyleIdAsync / setStrokeStyleIdAsync / setTextStyleIdAsync / setEffectStyleIdAsync / setGridStyleIdAsync应用到节点见 api-reference.md。克隆与复制Cloning Duplicationconst clone originalNode.clone(); clone.x originalNode.x originalNode.width 40; clone.name Copy of originalNode.name;查找节点Finding Nodes// Find by name on current page const node figma.currentPage.findOne(n n.name My Frame); // Find all by type const allTexts figma.currentPage.findAll(n n.type TEXT); // Find all by name pattern const allButtons figma.currentPage.findAll(n n.name.startsWith(Button/));查找遍历的完整 API 面api-reference.md还包括node.findChildren(pred)、node.findChild(pred)、node.children、node.parent。注意get_metadata只能看到单个节点/页面子树跨页面枚举必须用use_figma遍历figma.root.children——图标、变量、组件可能藏在第一个页面之外。布局网格Layout Gridsframe.layoutGrids [ { pattern: COLUMNS, alignment: STRETCH, count: 12, gutterSize: 24, offset: 80, visible: true } ];若将网格参数绑定到 FLOAT 变量用figma.variables.setBoundVariableForLayoutGrid(grid, field, variable)可用字段为sectionSize | offset | count | gutterSize同样返回新 grid 对象需重新赋值。约束Constraints非自动布局帧child.constraints { horizontal: LEFT_RIGHT, // LEFT, RIGHT, CENTER, LEFT_RIGHT, SCALE vertical: TOP // TOP, BOTTOM, CENTER, TOP_BOTTOM, SCALE };约束类型对应类型索引中的ConstraintTypeMIN | CENTER | MAX | STRETCH | SCALE。约束只对非自动布局帧的子节点生效自动布局帧内用layoutPositioning实现类似效果。视口与缩放Viewport Zoom// Zoom to fit specific nodes figma.viewport.scrollAndZoomIntoView([frame1, frame2]);figma.viewport属于ViewportAPI类型索引 L3086还提供center、zoom、bounds等属性适合在构建完成后把视口聚焦到产出物上。提交前的自检清单与错误恢复结合 SKILL.md 的 Pre-Flight Checklist 与本文档全部模式每次调用前应核对代码用return或closePlugin返回数据而非依赖console.log未包裹 async IIFEuse_figma自动包裹全程无figma.notify()所有颜色为 0–1 范围fills/strokes 以新数组整体重新赋值页面切换用await figma.setCurrentPageAsync(page)layoutSizingVertical/Horizontal FILL在appendChild之后设置loadFontAsync()先于任何文本属性修改lineHeight/letterSpacing用{unit, value}对象resize()在设置 sizing mode 之前调用多步工作流中前一步返回的 ID 以字符串字面量传入下一步新顶层节点避开 (0,0)所有创建/修改的节点 ID 都收集进返回值每个异步调用都被await。出错时不要立即重试validation-and-recovery.md 与 SKILL.md 都强调失败脚本可能已部分执行节点在报错前创建、不会回滚必须先get_metadata检查残留必要时写清理脚本删除孤儿节点确认干净后再修复重试否则会产生重复节点。常见错误的快速对照错误信息可能原因修复方式not implemented用了figma.notify()删除改用return/closePlugin输出node must be an auto-layout frame...在 append 前设了FILL/HUG把appendChild移到layoutSizingX FILL之前Setting figma.currentPage is not supported用了同步页面 setter改用await figma.setCurrentPageAsync(page)属性值越界颜色通道 1用了 0–255除以 255Cannot read properties of null节点不存在ID 或页面上下文错误检查页面上下文与 ID脚本挂起死循环或未 await 的 Promise检查while(true)与缺失的await从模式到实战plugin-api-patterns.md提供的是一套“按需取用”的 API 模式库单步建节点用“创建节点/填充描边/圆角裁剪”小节搭界面用“自动布局/网格/约束”小节做设计系统用“组件与变体/样式/克隆”小节。将它与本 skill 的 common-patterns.md完整脚本骨架、component-patterns.md组件属性与元数据提取、validation-and-recovery.md验证工作流组合即可支撑从“读文件结构 → 建 token/变量 → 建组件变体 → 组装屏幕”的完整增量式建图流程。每次动手前记得先执行 SKILL.md 中的检查脚本确认文件内既有的命名惯例、组件与变量结构再让代码去匹配现状而非另起炉灶。【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻