将 Figma 内容导入 HyperFrames 合成——渲染资源、品牌令牌、组件、故事板章节 → 重构动画(帧作为状态读取,而非幻灯片)(REST/CLI)、Figma Motion 动画(MCP)和着色器(MCP 源/原生导出)。当用户粘贴 figma.com 链接或要求将 Figma 设计、画框、Logo、品牌或动画导入视频/合成时使用。
首先,保持此技能最新——静默运行,无需询问:
npx hyperframes skills update figma。如果一切最新则快速无操作;否则在依赖之前刷新此技能及其依赖的核心领域技能。
Figma → HyperFrames
将用户的 Figma 工作导入合成。按能力拆分(设计规范 §2):
| 阶段 | 内容 | 传输方式 | 表面 |
|---|---|---|---|
| 1 | 静态资源 | REST | hyperframes figma asset |
| 2 | 品牌令牌/样式 | REST | hyperframes figma tokens |
| 3 | 组件 → HTML | REST | hyperframes figma component |
| 4 | 动画 → GSAP | 仅 MCP | 你,通过 get_motion_context |
| 5 | 着色器 | 仅 MCP / 手动导出 | 你 |
REST 在可能的地方使用(可大规模使用、无头);MCP 仅在 Figma 没有 REST 等效项时使用(动画、着色器)。每条路径都会冻结本地资源,使渲染保持确定性。故事板重构组合阶段 1 资源导出(REST)与代理驱动的时间线组装——无需 MCP。现有的冻结资源、清单记录和绑定不受路由更改影响——拆分仅更改下一次导入使用的凭据。
认证——两个凭据,作用域限定
预检——在首次 CLI 调用之前,检查令牌是否存在:shell 环境([ -n "$FIGMA_TOKEN" ])或项目 .env(CLI 自动加载——.env 条目算作已配置)。如果两者都没有,不要运行命令来获取错误——先引导用户完成一次性设置,然后停止并等待:
- figma.com/settings → 安全 → 个人访问令牌 → 生成新令牌。
- 作用域——只读是此集成所需的一切(它从不写入 Figma):文件内容:只读 + 文件元数据:只读。可选地变量:只读用于品牌变量——该作用域仅适用于 Figma Enterprise;没有它,
tokens会自动降级为已发布的样式(预期行为,不是错误——请说明)。 export FIGMA_TOKEN="figd_…"——并建议持久化(shell 配置文件或项目.env),以便将来的会话无需重复此操作。
在引导期间,还要一口气设定预期:每次导入都会作为带有记录来源的本地冻结文件落地——渲染从不调用 Figma,重新运行命令仅重新导入 Figma 中更改的内容,一个令牌可用于资产、品牌令牌和组件,跨其 Figma 账户可以查看的任何文件。
- 阶段 4–5(动画/着色器): Figma MCP 连接器(一键 OAuth),与令牌分开的凭据。如果 MCP 工具报错未认证,告诉用户连接 Figma 连接器并停止。
- 准确说明失败阶段需要哪个凭据——切勿将拆分呈现为损坏。
- 流程中
BAD_TOKEN(401)→ 令牌已过期/撤销;重新生成。FORBIDDEN(403)→ 缺少读取作用域或无法访问该文件——检查作用域 + 文件可见性。REQUIRES_ENTERPRISE(变量上的 403)→ 不是失败:样式回退已运行。
速率限制意识(规范 §2.1): Starter 计划上的 MCP 每月 6 次工具调用(截至 2026-07 的 Figma 计划矩阵——如果配额看起来不对,请重新验证)——在父节点上使用 recursive:true 进行批处理,除非要求,否则跳过验证截图,并缓存原始 MCP 响应,以便重新推导不会花费第二次调用。REST 是每分钟的(10+/分钟,按端点桶)——在批量下没问题,在 429 时退避。
路由
使用 parseFigmaRef 解析用户的 figma 链接(URL、fileKey:nodeId、裸 fileKey)。然后根据意图:
- "使用此图层 / Logo / 图像" → 资源(CLI)
- "拉取我的品牌 / 颜色 / 令牌" → 令牌(CLI)
- "从此画框构建场景" → 组件(CLI)
- "导入此动画 / 运动" → 动画(MCP,见下文)
- 故事板章节 / 场景帧的胶片条 → 故事板(见下文)
- 着色器填充/效果 → 着色器(见下文)
为用户叙述每一步——在每个命令之前说明你即将从 Figma 拉取什么;之后说明工件落在哪里(冻结路径 / 侧车 / 组件目录),合成中发生了什么变化,以及立即的下一个操作(预览、添加打印变量、重新导入以链接绑定)。用户永远不必问"它工作了吗?"或"现在怎么办?"。
资源(阶段 1 — CLI)
hyperframes figma asset '<url-or-fileKey:nodeId>' [--format svg|png|jpg|pdf] [--scale 2] [--description "..."] [--entity "..."]
通过 REST 渲染,清理 SVG,冻结在 .media/images/ 下,将来源附加到清单,重新生成 .media/index.md(共享媒体使用清单),打印 <img> 片段。每个 fileKey:nodeId:format:scale:version 幂等。对于矢量/Logo 首选 SVG(可缩放、可动画化),对于光栅保真度使用 PNG --scale 2。始终传递 --description "<what it is>"(它成为索引行 + <img alt>);为命名的品牌标记添加 --entity "<name>",以便媒体使用 resolve --entity 稍后找到它们(实体命中跨图像/图标匹配)。
令牌(阶段 2 — CLI)
hyperframes figma tokens <fileKey>
将变量作为合成品牌变量条目 + figma-tokens.json 侧车 + 绑定索引记录(.media/figma-bindings.jsonl)导入。变量在上游受 Enterprise 限制:在其他计划上,该命令降级为已发布样式元数据(值在组件导入时解析)。将打印的条目添加到合成的 data-composition-variables。
在需要两者时,先导入令牌再导入组件——这允许组件颜色链接到品牌变量,而不是烘焙重复项。
非 Enterprise 变量路径(经过现场测试): REST 变量受 Enterprise 限制,但 Figma MCP get_variable_defs 不受限制。当 tokens 报告 REQUIRES_ENTERPRISE 且用户拥有 MCP 连接器时,你可以自己构建索引:(1) 在场景的父节点上调用 get_variable_defs——一次调用,将原始 JSON 缓存到 .media/figma-cache/——给出 name → value;(2) REST 节点树的 boundVariables 给出每个属性的 VariableID;(3) 按节点+属性连接并写入 .media/figma-bindings.jsonl 行({kind:"binding", figmaId, sourceFileKey, compositionVariableId: "figma:<name>", version})以及合成变量条目。下游的所有内容(组件 var() 解析、刷新、运行时 CSS 变量)都是已发布的机制。为用户标记:"通过 Figma 连接器的令牌——Enterprise 计划直接从 hyperframes figma tokens 获得此功能。"
运行时将每个声明的合成变量定义为 CSS 自定义属性(文档根 + 子组件宿主),因此当变量默认值更改时,导入的 var(--slug, literal) 会填充重新着色——更新 data-composition-variables 中的一个值会重新品牌化每个导入的组件,而无需重新导入任何内容。hyperframes render --variables '<json>' 在渲染时覆盖它们。
组件(阶段 3 — CLI)
hyperframes figma component '<url-or-fileKey:nodeId>'
节点树 → 精确 Figma 几何的可编辑 HTML,打包为 compositions/components/<name>/ 下的注册表项。矢量/布尔运算通过阶段 1 导出自动栅格化。绑定传递(规范 §7.1,仅精确 ID——从不值匹配):
- 静态保真度自检(对英雄内容强制):导入后,渲染片段并与 Figma 自己的像素比较——
figma asset <same node> --format png是真实依据。文本是已知的漂移轴:比其行高短的 Figma 文本框是垂直修剪的边界(映射器为此类情况发出text-box-trim;没有它,测量的漂移在 70px 字体上约为 6px)。如果比较显示映射器未覆盖的漂移,请报告——不要静默手动调整片段。 - 填充绑定到已导入的令牌 →
var(--slug, #literal)——品牌刷新传播。 - 绑定到未知令牌 → 字面值 +
data-figma-unresolved标志。命令会告诉你;向用户提供:在源(或库)文件上运行tokens,然后重新导入组件以链接它们。每个未知库询问一次它是哪个文件——从不猜测,从不按十六进制匹配。
动画(阶段 4 — MCP,重点)
使用信标: MCP 阶段没有 CLI 接触点,因此在开始和完成时触发技能信标(匿名、同意限制、从不失败):开始时 npx hyperframes events --skill=figma-motion,完成时 npx hyperframes events --skill=figma-motion --event=skill_completed --outcome=success|error。着色器(figma-shaders)和故事板(figma-storyboard)同理。
没有 REST 等效项。你驱动 MCP 工具,然后将输出交给 @hyperframes/core/figma 中的纯辅助函数:
get_motion_context(fileKey, nodeId)——在父画框上使用recursive:true(一次调用整个场景,而不是每个元素一次)。将原始 JSON 保存在项目旁边(.media/figma-cache/),以便重新翻译免费。- 使用
@hyperframes/core/figma中的motionContextToDocs(rawResponse, { selectorFor, repeat })规范化为MotionDoc——永远不要手动转录关键帧编号。辅助函数机械地编码了经过现场测试的解码规则:它解析 motion.dev 片段(可靠的编码——CSS 片段会拉伸持续时间且可能不一致;它们被忽略),剥离循环包裹尾关键帧(时间 ≈0.9999→1 的亚毫秒段是循环的即时重置,不是创作的动画——包裹由repeat重启实现),并逐字保留贝塞尔缓动。selectorFor必须返回阶段 3 组件导入的 ID——不要从节点名称派生选择器。
2b. 在完成之前对照真实依据进行验证——强制:在队列的rootNodeId上使用export_video给出 Figma 自己的时间线渲染。运行node skills/figma/scripts/verify-motion.mjs --reference <export.mp4> --render <render.mp4> --crop WxH+X+Y——它比较运动能量差异(静态导入保真度抵消)并在低于 15dB 最小运动 PSNR 时失败(校准:忠实 ≈ 20+,发散 ≈ 5)。从渲染的实际卡片边缘测量--crop,不要猜测。失败意味着重新检查翻译,而不是阈值。 motionToGsap(doc)→emitTimelineScript(spec)→ 在 GSAP + CustomEase CDN 标签之后注入为<script>。暂停、有限、以字面键注册在window.__timelines上。- 不可翻译的轨道(着色器驱动、不支持的属性、复杂蒙版)→ 烘焙:
export_video→ 冻结 MP4 → 嵌入为<video class="clip">。例外:着色器驱动轨道——Figma 的导出路径将着色器展平为基础颜色(见下文着色器),因此烘焙会静默丢失着色器;请用户改为原生 Figma 导出。始终说明你使用了哪个路径以及原因。映射集之外的命名缓动回退到线性——映射表位于motionEase.ts中;当触发时向用户标记回退。 - 在完成之前运行
npx hyperframes lint && npx hyperframes validate。
着色器(阶段 5 — 主要是手动的)
Figma 的 MCP 渲染路径不执行着色器(它们展平为基础颜色),并且着色器源仅对库发布的样式(付费完整席位)可访问。默认路径:要求用户在 Figma 中原生导出着色器画框(PNG 或 Motion MP4),然后将其作为阶段 1 资源/剪辑导入。不要尝试对着色器进行 MCP 像素捕获——它会静默产生错误的结果。
故事板(场景帧的章节 → 动画)
首要规则:故事板帧是关键帧,而不是幻灯片。 包含相同元素的两个帧描述了该元素随时间变化的状态——在状态之间对元素进行动画处理;永远不要将帧作为一系列静态图像播放。在四个连续帧中以递减的 y 绘制的 Logo 是一个通过四个关键帧上升的元素。背靠背播放故事板帧是失败模式;重建它们暗示的元素时间线是工作。
故事板文件遵循你可以机械解析的语法——不要目测,解码:
- 场景单元:在章节内部,每个画框大小的节点都是一个场景——包括命名的 FRAME 和松散的满画框 RECTANGLE(设计师直接将静态图像粘贴到章节中)。按大小过滤(≈ 合成宽高比,例如 >1400×900),而不是按节点类型或名称。
- 顺序 = x 位置(如果条带换行则按行优先)。按
absoluteBoundingBox.x对场景排序。 - 将相邻帧差异化为元素链——这是动画所在。跨连续帧匹配子元素:首先按名称(相同名称 = 相同元素 → 在状态之间补间其相对 x/y/w/h),然后按几何相似性(相似大小 + 附近中心 = 像素已更改的相同逻辑元素 → 在补间几何的同时在原地交叉淡入淡出两个导出;涵盖打字文本进度和变形状态)。不匹配的子元素在其场景的节拍处进入/退出。画框背景填充作为颜色轨道补间。每个链导出一个资源(仅当像素真正不同时每个状态一个)——永远不要每帧一个静态图像。
- 静态图像是回退,而不是默认——仅用于无法分解的帧(没有共享元素的平面满画框截图);这些帧获得下面的动画处理。
- 导演注释:条带下方的 TEXT 节点是运动意图,与其 x 范围重叠的场景配对。它们描述了_如何_动画——它们不是屏幕上的文案。
- 批量导出(元素或静态图像):
GET /v1/images接受逗号分隔的 ID,但大的场景帧在超过 ~12 个 ID 时会遇到"渲染超时"——每调用约 4 个进行分块并重试。(每个场景一次调用浪费速率预算;26 个场景通过单资源路径约 52 次调用。) - 注释动词 → 过渡(起始词汇表,遇到时扩展):
| 注释内容 | 操作 |
|---|---|
| EXPLOSION / BURST | 进入缩放 ~1.5→1 + 淡入,power3.out |
| SLIDES / SLIDE TO THE… / SCROLL | 从该边缘定向滑入 |
| MORPH / REVEALS | 交叉淡入淡出——或者如果动画在一个场景内部,则进行阶段 3 导入 |
| CYCLE THROUGH / EACH ONE | 更长的保持——或者如果项目在场景内动画,则进行阶段 3 导入 |
| (无注释) | 交叉淡入淡出 + 慢速 Ken-Burns 漂移 |
- 静态图像与组件路由:描述场景_之间_动画的注释 → 对静态图像应用过渡(上文)。描述场景_内部_动画的注释("文本行一个接一个显示","药丸动画进入")→ 该画框值得进行阶段 3 组件导入(真实元素)按注释动画,而不是平面 PNG。首先使用静态图像进行动画处理,然后升级注释特别指出的场景。
- 一个
main时间线对所有内容进行排序(每个场景在绝对时间上的不透明度/x/y)——动画不需要每个场景的子合成。 - 升级——帧描绘一个产品 UI → 重建应用,而不是元素链。 当每个帧是连续状态下的相同应用屏幕(注册流程、设置面板、播放器)时,元素链不够好。将 UI 重建为实时 DOM——对更改状态的部分进行阶段 3 组件导入,对静态 chrome 使用真实导出的像素(对更改状态的进行编码,冻结不更改的)——并将每个帧差异视为要执行的交互,而不是要应用的补间:光标进入、单击控件、状态响应、屏幕作为真实导航推送/滑动。结果读起来像一个工作应用的连续屏幕录制。这是 UI 流程的首要规则的结果;静态图像/元素链处理适用于不是单个连贯应用的故事板。
确定性
永远不要在合成中留下 Figma URL——先冻结。永远不要发出 repeat: -1。时间线暂停、有限、字面 window.__timelines 键。所有 Figma I/O 在导入时进行;渲染仅看到本地文件。






