Agent skill

scene-dev

NextFrame Scene 组件开发规范。创建新 scene、修改 scene、审查 scene 质量。 确保每个 scene 满足 ADR-008 强制契约:4 接口 + 主题预设 + AI 元数据 + preview + validate 全绿。 TRIGGER: "写组件"、"新 scene"、"做 scene"、"加组件"、"scene 开发"、"组件开发"、 "写背景"、"写标题"、"写图表"、"写叠加层"、"新 scene"。 DO NOT TRIGGER when: 使用已有 scene 写 timeline、修 engine 代码。

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/scene-dev

SKILL.md

NextFrame Scene 开发规范(ADR-008 强制契约)

核心原则(违反 = 打回重做)

1. 一个 scene = 一个视觉原子

一个 scene 只做一件事。 不混合多个视觉职责。

正确 错误
flowDiagram 只画节点+箭头 flowDiagram 同时画标题+流程图+引语
titleCard 只画标题 titleCard 同时画标题+代码块
subtitleBar 只画字幕 subtitleBar 同时画字幕+进度条

判断标准:如果你的 scene 里有两种"能独立存在"的内容,就该拆成两个 scene。

标题是标题 scene。引语是引语 scene。流程图是流程图 scene。组合靠 timeline 的 layers。

2. 参数不写死视觉

  • 颜色、位置、大小 → 全部走 params,不硬编码
  • 文字内容如果支持 HTML(加粗/变色)→ 在 meta.params 里标注 semantic: "supports inline HTML"
  • 不支持 HTML 的文字 → 必须 esc() 转义

3. 先预览后提交

写完 index.js + preview.html → 必须打开 preview.html 自己看一遍 → 确认无溢出、无错位、动画流畅 → 才能提交。

开发流程(必须按顺序,每步都有阻断检查)

1. 确定职责 → 这个 scene 只做什么?(一句话说清,超过一句就该拆)
2. 确定比例 + 类别 → 创建目录
3. 写 index.js(meta 全字段 → render → screenshots → lint)
4. 写 preview.html(自包含,file:// 可打开,不依赖服务器)
5. ⛔ 打开 preview.html 自己看 → 确认视觉正确
6. validate-scene.js 全绿
7. 测试 lint 拦截(故意传错参数)
8. 做一个 demo timeline 验证组合效果(和其他 scene 叠加)
9. 提交

步骤 5 是阻断点。 不看 preview 不许提交。看到问题必须修完再走下一步。

目录结构(强制)

src/nf-core/scenes/{ratio}/{category}/{sceneName}/
├── index.js        ← 必须:meta + render + screenshots + lint
└── preview.html    ← 必须:自包含,file:// 直接打开

比例目录(禁止 universal):16x9/ | 9x16/ | 4x3/ 类别目录:backgrounds/ | typography/ | data/ | shapes/ | overlays/ | media/ | browser/

index.js — 4 个必须导出 + 强制 meta 字段

meta(全字段必填)

js
export const meta = {
  // ─── 身份 ───
  id: "sceneName",              // 唯一 ID
  version: 1,                   // 改接口就 +1
  ratio: "9:16",                // 必填,禁止 null,和目录一致

  // ─── 分类与发现 ───
  category: "backgrounds",      // 小写
  label: "Scene Name",          // 英文名
  description: "中文描述,说清楚视觉效果和动画行为",
  tags: ["tag1", "tag2", "tag3"], // 至少 3 个搜索标签
  mood: ["calm", "energetic"],    // 情绪标签
  theme: ["tech", "business"],    // 适用主题

  // ─── 渲染 ───
  tech: "canvas2d",             // canvas2d | webgl | svg | dom | video | lottie
  duration_hint: 12,            // 建议时长(秒)
  loopable: true,               // 能否循环
  z_hint: "bottom",             // bottom | middle | top

  // ─── 主题预设(至少 3 个)───
  default_theme: "theme-name",
  themes: {
    "theme-name": { /* params 子集 */ },
    // 至少 3 个预设
  },

  // ─── 参数 ───
  params: {
    paramName: {
      type: "number",           // number | string | boolean | color | enum | array | object | file
      default: 270,             // 必须有(除非 required: true)
      range: [0, 360],          // number 必须有
      step: 1,                  // number 必须有
      label: "中文名",          // 必须有
      semantic: "english desc for AI", // 必须有,写清楚含义和取值范围的效果
      group: "color",           // content | color | style | animation | shape
    },
  },

  // ─── AI 指南(全字段必填)───
  ai: {
    when: "什么场景适合用,中文",
    how: "怎么在 timeline 里用,中文",
    example: { /* 完整 params 示例 */ },
    theme_guide: "每个 theme 的中文一句话说明",
    avoid: "什么情况不要用",
    pairs_with: ["scene-id-1", "scene-id-2"],
  },
};

render(t, params, vp) → HTML string

js
export function render(t, params, vp) {
  const { width, height } = vp; // 画布尺寸(像素)
  // 返回 HTML 片段
}

强制规则:

  • 纯函数 — 相同 (t, params, vp) → 相同输出
  • 禁止 Math.random()(除非用 seed)、Date.now()、全局状态
  • 禁止 setTimeout / setInterval / requestAnimationFrame / fetch
  • 返回的 HTML 宽高 = vp.width × vp.height
  • 只做自己那一件事的 HTML。 不画别的 scene 该画的东西

按 tech 类型的输出格式:

tech 返回什么 注意
canvas2d <canvas width={W} height={H}> + <script>绘制</script> canvas 尺寸 = vp,不要写死 1080
svg <svg viewBox="0 0 {W} {H}"> viewBox 天然缩放
dom <div style="width:{W}px;height:{H}px"> 尺寸跟 vp 走
webgl <canvas> + WebGL init <script>
video <video src currentTime={t}>
lottie Lottie player 定位到 t 帧

⚠️ 踩坑记录:Canvas 和 DOM 混合渲染时,所有 scene 必须用同一个 viewport 尺寸。不要 Canvas 用 1080 而 DOM 用 380。

screenshots() → 截图时间点

js
export function screenshots() {
  return [
    { t: 0,   label: "开始" },
    { t: 2.5, label: "动画中" },
    { t: 4.5, label: "完成" },
  ];
}

至少 3 个:开始、中间、结束。label 用中文。

lint(params, vp) → 检查结果

js
export function lint(params, vp) {
  const errors = [];
  // 必须检查:
  // 1. 文字溢出安全区(viewport × 0.9)
  // 2. 数组长度合理
  // 3. required 参数非空
  // 4. 数值在 range 内
  // 5. theme 名字在 themes{} 里存在
  // 每个 error 格式:"描述。Fix: 修复建议"
  return { ok: errors.length === 0, errors };
}

preview.html 规范

必须自包含: file:// 直接打开,不依赖服务器,不用 ES module import。render 函数直接内联到 HTML 里。

必须有的 UI 元素:

  1. 正确比例的画布(16:9 → 960×540 缩放容器)
  2. 进度条(可拖动跳转)
  3. 播放/暂停按钮
  4. 时间显示
  5. 暖棕背景 #1a1510(模拟真实合成环境)

渲染规则:

  • Canvas:画在显示尺寸上(不要画 1080 再 CSS 缩小,会卡)
  • SVG:用 viewBox,天然清晰
  • DOM:用 1920×1080 内部容器 + transform:scale(0.5) 缩放

渲染技术选择

场景类型 推荐 tech 原因
渐变/粒子/噪声 canvas2d 像素级操作
3D/Shader webgl GPU 加速
图表/图形 svg 矢量不糊
文字排版/卡片/毛玻璃 dom CSS 排版 + backdrop-filter
视频片段 video HTML5 Video
设计师动画 lottie .json 格式

主题系统

json
// timeline 里用法(3 种):
// 1. 只选 theme(AI 安全选择)
{ "scene": "auroraGradient", "theme": "ocean-teal" }

// 2. theme + 微调
{ "scene": "auroraGradient", "theme": "ocean-teal", "params": { "intensity": 1.5 } }

// 3. 纯自定义
{ "scene": "auroraGradient", "params": { "hueA": 150 } }

合并优先级:params.default < themes[name] < timeline.params

验证命令

bash
# 验证单个(16 项检查)
node src/nf-core/scenes/validate-scene.js <scene-dir>

# 验证全部
for d in $(find src/nf-core/scenes -name "index.js" -exec dirname {} \;); do
  node src/nf-core/scenes/validate-scene.js "$d"
done

# 测试 lint 拦截
node src/nf-core/scenes/validate-scene.js <dir> --params '{"text":"超长文字..."}'

# 预览
open <scene-dir>/preview.html

# 做 demo timeline 测试组合
# 参考 output/demo-9x16.html

质量标准(全部必须满足)

# 检查项 标准
1 单一职责 scene 只做一件事,能一句话说清
2 无溢出 preview 里看不到任何内容超出画布/容器
3 validate-scene.js 16/16 通过
4 preview.html 打开能看到流畅动画,file:// 直接可用
5 lint 拦截 故意传溢出/空值能报错带 Fix 建议
6 render 纯函数 相同输入 → 相同输出
7 主题预设 至少 3 个 theme,default_theme 有效
8 AI 元数据 when/how/example/theme_guide/avoid/pairs_with 全有
9 组合测试 在 demo timeline 里和其他 scene 叠加不冲突

常见错误(做 scene 时必须检查)

错误 怎么发现 怎么修
一个 scene 混了多种内容 description 要写两句话才能说清 拆成多个 scene
文字溢出容器 preview 里文字超出画布边界 自适应字号 / 限制最大宽度 / lint 拦截
HTML 标签被转义显示 看到 <span> 字样 支持 HTML 的字段不 esc(),在 semantic 里标注
颜色硬编码 换 theme 颜色不变 全部走 params,themes 覆盖
preview 需要服务器 file:// 打开白屏 不用 ES module import,render 函数内联
不自验就提交 用户看到溢出/错位 必须 open preview 自己看一遍

已有 scene 组件(16:9)

Scene 类别 职责(一件事)
auroraGradient backgrounds 渐变光斑背景
codeTerminal browser 终端代码块
slideChrome overlays 顶栏 + 水印
titleCard typography 大标题 + 副标题
tagCompare typography 两个对比标签
eventList data 竖排圆点列表
flowDiagram data 节点箭头流程图(不含标题/引语)
subtitleBar overlays 底部字幕
progressBar overlays 进度条
barChartReveal data 柱状图
kineticHeadline typography 逐字出现标题

缺的(待做):

  • headlineCenter — 居中大标题(独立于 titleCard 的全屏居中版)
  • quoteBlock — 金色斜体引语
  • comparisonPanel — 左右对比卡片(主 Agent vs 子 Agent)
  • stackedCards — 堆叠卡片列表(九层配置等)

Expand your agent's capabilities with these related and highly-rated skills.

Didn't find tool you were looking for?

Be as detailed as possible for better results