Figma Effect Styles 实战指南:用 Plugin API 构建可复用的阴影与模糊 Token 系统
【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills
Effect Style(效果样式)是 Figma 中把投影、内阴影、模糊等视觉效果封装为具名、可复用定义的机制,也是设计系统中"阴影/高度(elevation)Token"在 Figma 侧最贴近的等价物。本文以本仓库figma-useSkill 的 wwds-effect-styles.md 为核心骨架,结合 plugin-api-standalone.d.ts 的类型定义与 effect-style-patterns.md 的可运行代码模式,系统讲解 EffectStyle 的数据模型、四种 Effect 类型、变量绑定机制以及创建/枚举/应用的全流程,帮助你通过use_figmaSkill 用 Plugin API 把设计系统里的阴影规范变成真实的 Figma 文件内容。
Effect Style 是什么:阴影与模糊的"命名 Token"
在 Figma 的设计系统语境中,Effect Style 是一个或多个视觉效果的具名、可复用定义——这些视觉效果包括投影(drop shadow)、内阴影(inner shadow)和模糊(blur)。从设计系统的角度看,它最接近代码侧的 shadow / elevation token:团队可以预先定义Elevation/100、Elevation/200这样的效果样式,然后在任意节点上一键复用,保证全文件阴影规范一致。
需要特别区分的是:Effect Style 与 Variables(变量)是两套不同的机制。Figma 中没有单独一种变量类型能够直接表示一个阴影。但反过来,效果内部的单个数值属性与颜色属性(如color、radius、spread、offsetX、offsetY)是可以绑定到变量上的。这意味着阴影既可以作为整体被样式复用,其构成参数又能接入 Token 体系参与明暗主题切换,两条路径互补而不冲突。相关设计系统总体理念可参考 wwds.md。
EffectStyle 数据模型:一个核心可写属性 + 继承字段
在 plugin-api-standalone.d.ts 中,EffectStyle接口的定义如下:
interface EffectStyle extends BaseStyleMixin { type: 'EFFECT' effects: ReadonlyArray<Effect> readonly boundVariables?: { readonly [field in VariableBindableEffectStyleField]?: VariableAlias[] } }除继承自BaseStyleMixin的字段外,EffectStyle只有一组核心可写属性,归纳如下:
| 属性 | 类型 | 说明 |
|---|---|---|
name | string | 样式名称,用/分隔以形成分组,例如"Elevation/200" |
effects | ReadonlyArray<Effect> | 只读数组—— 必须克隆、修改后再整体重新赋值 |
description | string | 从BaseStyleMixin继承的描述字段 |
type | 'EFFECT' | 类型判别字面量,读取其他属性前应始终先检查type |
boundVariables | Readonly | 该效果样式上各字段绑定的变量别名(只读) |
BaseStyleMixin(见 plugin-api-standalone.d.ts)还提供id(只读)、name、getStyleConsumersAsync()(查询样式消费者)和remove()(删除本地样式)等能力,其中id正是后续把样式应用(assign)到节点时要用到的关键值。
Effect 类型详解:判别联合下的四种常用形态
Effect是一个判别联合(discriminated union)。在 plugin-api-standalone.d.ts 中,完整的联合成员包括DropShadowEffect | InnerShadowEffect | BlurEffect | NoiseEffect | TextureEffect | GlassEffect。其中最常见的四种类型及关键属性如下:
type | 关键属性 | 备注 |
|---|---|---|
DROP_SHADOW | color: RGBA、offset: Vector、radius: number、spread: number、visible: boolean、blendMode | 外投影,可额外设置showShadowBehindNode |
INNER_SHADOW | 与DROP_SHADOW相同 | 内阴影,spread为正时向内收缩 |
LAYER_BLUR | radius: number、visible: boolean | 图层模糊 |
BACKGROUND_BLUR | radius: number、visible: boolean | 背景模糊(毛玻璃效果) |
对照类型定义(plugin-api-standalone.d.ts)可以确认几个实现细节:
- 阴影的
color是RGBA(即{ r, g, b, a }四个 0–1 之间的数值),offset是Vector(即{ x, y }); radius必须>= 0,数值越小阴影越锐利;spread为可选字段,默认值为 0;正 spread 让外投影大于节点、内阴影向内收缩,负值则相反。且 spread 只在矩形、椭圆,以及带有可见填充且开启clipsContent的 Frame/Component/Instance 上生效;- 模糊类型(
LAYER_BLUR/BACKGROUND_BLUR)只关心radius与visible两个属性。
务必牢记的颜色规范:所有效果颜色均为 0–1 区间的RGBA分量,不是0–255,也不是十六进制。例如半透明黑色应写作{ r: 0, g: 0, b: 0, a: 0.15 }。这是use_figmaSkill 的强制性规则之一(见 SKILL.md 的 Critical Rules 第 6 条),颜色通道大于 1 是运行时报错的高频原因。
变量绑定:让阴影参数参与 Token 系统
尽管效果样式本身不能整体绑定变量,但单个属性可以通过setBoundVariableForEffect(effect, field, variable)绑定到变量上(可在节点上调用,也可在构造时内联绑定)。可绑定的字段(VariableBindableEffectField,见 plugin-api-standalone.d.ts):
'color' | 'radius' | 'spread' | 'offsetX' | 'offsetY'其中color绑定 COLOR 类型变量,radius/spread/offsetX/offsetY绑定 FLOAT 类型变量;模糊效果则只有radius(FLOAT)可以绑定。api-reference.md中给出的绑定模式如下(见 api-reference.md):
// Binding variables to effects (COLOR/FLOAT variables) const newEffect = figma.variables.setBoundVariableForEffect(effectCopy, field, variable) // field for shadows: "color" (COLOR), "radius" | "spread" | "offsetX" | "offsetY" (FLOAT) // field for blurs: "radius" (FLOAT) // ⚠️ Returns a NEW effect — must capture return value! node.effects = [newEffect]根据 plugin-api-standalone.d.ts 的类型签名,setBoundVariableForEffect返回一个绑定后的新 Effect 对象副本;如果传入variable = null,则会解除该字段的绑定。因此使用时的铁律是:
- 把调用返回值捕获下来;
- 再整体重新赋值给
effects数组(注意node.effects同样是一个只读数组,禁止原地修改)。
这正是效果参与明暗双主题切换的机制:把阴影颜色和偏移绑定到主题变量后,切换模式即可全局联动。
实战:枚举、创建与应用 Effect Style
本仓库的 effect-style-patterns.md 提供了三个可直接运行的核心模式。注意:在use_figmaSkill 环境中,代码应使用顶层await与return返回数据,不要包裹 async IIFE、不要调用figma.closePlugin()(见 SKILL.md);以下代码保留了原文在标准 Plugin 环境下的写法,便于对照。
1. 枚举本地所有 Effect Style
/** * Lists all local effect styles. * * @returns {Promise<Array<{id: string, name: string, key: string, effectCount: number}>>} */ async function listEffectStyles() { const styles = await figma.getLocalEffectStylesAsync(); return styles.map(s => ({ id: s.id, name: s.name, key: s.key, effectCount: s.effects.length })); }在标准 Plugin 环境下的完整运行脚本:
(async () => { try { const results = await listEffectStyles(); figma.closePlugin(JSON.stringify(results)); } catch(e) { figma.closePluginWithFailure(e.toString()); } })()API 演进提醒:getLocalEffectStyles()(同步版本)已被标记为@deprecated(见 plugin-api-standalone.d.ts),当插件 manifest 声明了"documentAccess": "dynamic-page"时它会直接抛异常;请始终使用getLocalEffectStylesAsync()。
2. 创建投影 Effect Style
创建的核心是figma.createEffectStyle()(见 plugin-api-standalone.d.ts)。以下函数演示了如何构造一个标准投影样式,包含颜色(RGBA 0–1)、偏移、模糊半径与 spread:
/** * Creates a drop shadow effect style. * * @param {string} name - e.g. "Elevation/200" * @param {{ r: number, g: number, b: number, a: number }} color - RGBA, 0-1 range * @param {{ x: number, y: number }} offset * @param {number} radius - blur radius * @param {number} [spread=0] * @returns {EffectStyle} */ function createDropShadowStyle(name, color, offset, radius, spread) { const style = figma.createEffectStyle(); style.name = name; style.effects = [{ type: "DROP_SHADOW", color, offset, radius, spread: spread || 0, visible: true, blendMode: "NORMAL" }]; return style; }完整运行脚本(创建"Elevation/200"样式:黑色 15% 透明度、向下偏移 4、模糊 12、无 spread):
(async () => { try { const style = createDropShadowStyle( "Elevation/200", { r: 0, g: 0, b: 0, a: 0.15 }, { x: 0, y: 4 }, 12, 0 ); figma.closePlugin(JSON.stringify({ id: style.id, name: style.name })); } catch(e) { figma.closePluginWithFailure(e.toString()); } })()命名建议使用斜杠分隔以形成层级分组(如"Elevation/200"),这与设计系统中 token 的层级命名规范一一对应。
3. 把 Effect Style 应用到节点
应用的本质是把样式的id赋给节点的effectStyleId属性——赋值后节点的effects属性会自动反映该样式的值。注意effectStyleId并不是所有节点都具备的属性,因此应用前要做能力探测:
/** * Applies an effect style to all nodes on the current page that match a given name pattern. * * @param {string} styleId - The ID of an EffectStyle. * @param {string} nodeNamePattern - Substring match against node names. * @returns {number} - Number of nodes the style was applied to. */ function applyEffectStyleToMatchingNodes(styleId, nodeNamePattern) { const nodes = figma.currentPage.findAll(n => n.name.includes(nodeNamePattern)); let applied = 0; for (const node of nodes) { if ('effectStyleId' in node) { node.effectStyleId = styleId; applied++; } } return applied; }完整运行脚本(把名为'STYLE_ID'的样式应用到所有名称包含'Card'的节点):
(async () => { try { const applied = applyEffectStyleToMatchingNodes('STYLE_ID', 'Card'); figma.closePlugin(JSON.stringify({ applied })); } catch(e) { figma.closePluginWithFailure(e.toString()); } })()dynamic-page 模式的补充:根据 plugin-api-standalone.d.ts 的说明,如果插件 manifest 包含"documentAccess": "dynamic-page",effectStyleId属性变为只读,此时应改用setEffectStyleIdAsync(styleId)异步方法来更新样式引用。
常见陷阱(Common Gotchas)
把上面所有内容浓缩成五条最容易踩坑的规则:
effects是只读数组:不能原地 push/mutate。必须克隆、修改、再整体重新赋值,例如style.effects = [...style.effects, newEffect];对节点的node.effects同样如此。- 效果按数组顺序堆叠:数组中的效果顺序直接影响视觉结果——投影按从底部到顶部的顺序渲染,多阴影叠加时顺序不同观感完全不同(多层投影的典型写法见 plugin-api-patterns.md)。
- 颜色一律是 RGBA 0–1:
{ r: 0, g: 0, b: 0, a: 0.15 }这样的写法,而不是 hex、不是 0–255。若某次运行报"Property value out of range",先检查是否误用了 0–255 的色值。 getLocalEffectStyles()已废弃:始终使用异步的getLocalEffectStylesAsync()。- 样式不会自动生效:创建
EffectStyle不会对任何节点产生影响,只有把它的id赋给节点的effectStyleId后才会真正应用。
在 use_figma 环境中执行的额外注意事项
通过本仓库的figma-useSkill 调用use_figmaMCP 执行上述代码时,还需遵守 Skill 的运行环境约束(详见 SKILL.md):
- 代码自动包裹在 async 上下文中,用顶层
await与return返回结果,不要使用figma.closePlugin()或(async () => { ... })()包装; return值是唯一的输出通道,console.log()不会被回传;所有新建/修改的节点或样式 ID 必须结构化返回(如return { createdStyleIds: [...] }),供后续调用引用与校验;- 每次调用会重置页面上下文,多步工作流建议"创建样式 → 校验 → 应用"分步执行,每步用
get_metadata验证结构; - 脚本失败是原子的——出错时整个脚本不会执行,文件保持原状,先仔细阅读错误信息再修正重试,不要盲目立即重试。
小结与延伸阅读
Effect Style 是设计系统 Token 链路中"高度/阴影"语义的落点:用命名样式统一视觉规范,用变量绑定接通主题切换,再用effectStyleId让任意节点一键套用。掌握了createEffectStyle()、getLocalEffectStylesAsync()、setBoundVariableForEffect()与effectStyleId这四件套,你就能用 Plugin API 完整落地阴影 Token 体系的创建、查询、绑定与应用。
- 完整可运行代码:阅读 effect-style-patterns.md;
- 精确类型签名:在 plugin-api-standalone.d.ts 中 grep
EffectStyle、DropShadowEffect、setBoundVariableForEffect、VariableBindableEffectField等符号; - 其他效果写法的直接示例(投影、内阴影、背景模糊、图层模糊、多阴影叠加):plugin-api-patterns.md;
- 变量绑定的完整 API 对照表:api-reference.md;
- 设计系统工作总纲与其余范式(Components / Variables / Text Styles):wwds.md。
【免费下载链接】skillsSkills Catalog for Codex项目地址: https://gitcode.com/GitHub_Trending/skills4/skills
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考