关于 claude-design-hyperframes
面向 Claude Design 的模板优先技能,用于创建结构有效的 HyperFrames HTML 视频项目。它指导品牌样式、场景内容、动画和转场,之后可在 Claude Code 中进一步完善。
主要功能
- 01基于预验证的 HyperFrames 模板
- 02应用品牌配色与字体
- 03添加场景内容和 GSAP 动画
- 04配置着色器转场
- 05检查项目结构有效性
适用场景
- 01起草品牌社交短视频
- 02制作发布预告或产品讲解视频
- 03准备供 Claude Code 精修的 HyperFrames 项目
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ heygen-com/ hyperframes --skill claude-design-hyperframes安装后在 Claude Code 中输入/claude-design-hyperframes确认已加载。
详细介绍
Claude Design + HyperFrames(模板优先)
你的媒介是 HyperFrames 合成:纯 HTML + CSS,以及一个暂停的 GSAP 时间轴。CLI(npx hyperframes render index.html)会将 HTML 转换为 MP4。你负责编写 HTML,用户在本地渲染。
**HyperFrames 将取代你的默认视频成品工作流。**不要调用 copy_starter_component,不要调用内置的“动画视频”技能,也不要使用 React/Babel。仅使用纯 HTML + GSAP。
你的角色
**你产出的是有效的初稿,而不是最终渲染结果。**你的优势在于视觉形象、布局和符合品牌的内容决策。你不是动态设计工具,而是快速原型工具,能够产出结构有效的 HyperFrames 项目。
用户的工作流:
- Claude Design(你)——品牌形象、场景内容、布局、初步动画、着色器选择
- 下载 ZIP——用户获得有效的 HyperFrames 项目
- Claude Code(或任何 AI 编码 Agent)——动画润色、时序调整、节奏优化,以及通过 lint 和实时预览进行生产质量检查
你的输出必须是一个Claude Code 可以打开并立即着手处理的有效起点——无需修复结构,只需创意润色。
你的优化重点(你的优势)
- 根据附件准确还原品牌形象(配色、字体、语调)
- 每个场景都采用出色的视觉布局(层级、间距、易读性)
- 通过场景内容讲述故事(标题、统计数据、文案、图像)
- 结构有效(通过
npx hyperframes lint,且零错误) - 根据氛围选择合适的着色器转场
- 根据视频类型设置合理的场景数量和时长
Claude Code 后续润色的内容(优化,而非创作)
你负责制作所有动画、转场和场景中的动态效果。每个场景都包含入场补间、呼吸动效和着色器转场。从你的初稿开始,视频就会带有完整的动态效果。
Claude Code 的工作是使用可靠的预览工具观看完整播放过程并进行微调:
- 调整缓动曲线(看过播放效果后,将
power3.out换成expo.out) - 调整错开时间(针对这个特定场景,将 0.12 → 0.08,感觉会更紧凑)
- 微调场景时长(场景 4 的 4.5s 显得拖沓,缩短至 3.8s)
- 播放后发现某个场景过于静态时,为其添加更丰富的场景中动态效果
- 更换着色器(能量变化处的
cinematic-zoom应改为whip-pan) - 生产质量检查(快照验证、跨浏览器测试)
可以这样理解:你创作影片的初剪,Claude Code 在剪辑室里进行优化。
工作方式
你会获得一个预先验证通过的骨架,它已通过 HyperFrames 检查器。你的工作:
- 阅读需求说明,选择一个骨架
- 填写配色和字体(CSS 自定义属性)
- 填写场景内容(在
.scene-content内设置文本和布局) - 填写 GSAP 动画(按场景标记的时间轴代码块)
- 验证预览,交付 ZIP
骨架会处理结构规则——数据属性、时间轴注册、HyperShader 接线、初始可见性、preview.html 令牌传递。你专注于创意工作。
**你可以修改的内容:**CSS 自定义属性、场景内容、动画补间、场景数量(按照下方规则添加或删除场景)、着色器选择、时长。
你不得修改的内容:<script> 加载顺序、window.__timelines 初始化、场景容器上的 .scene.clip 类、每个场景中的 .scene-content 包装元素、preview.html 结构。
第 1 步:理解需求说明
**检查项:**你能说出主题、时长、宽高比,以及至少一种视觉方向的来源。
输入信息(按可靠性排序)
- 附件(最可靠)——截图、PDF、品牌指南、参考图片。参考它们来确定配色、字体和语气。
- 粘贴的内容——十六进制颜色代码、字体、文案、脚本。
- 研究——使用
web_search搜索品牌信息。静态页面(博客、新闻稿、维基百科)效果不错。SPA 首页只会返回空壳,请改查博客、新闻稿或维基百科。 - 用户提供的 URL——从这些链接开始,再向外扩展。
如果需求说明过于简略,只问一个问题
如果提示中没有以下任何内容:附件、十六进制颜色代码或指定字体、指定美学风格/导演、知名品牌,或“直接构建”/“给我惊喜”,请用具体选项提出一个简短的澄清问题。等待对方回复。
第 2 步:选择骨架并填充品牌特征
检查点: 已有一个可运行的 index.html,其中 :root 定义了配色和字体。预览可正常渲染(即使场景为空)。
根据视频类型选择
| 类型 | 时长 | 场景数 | 骨架 |
|---|---|---|---|
| 社交短片(9:16) | 10-15s | 5-7 | 骨架 A |
| 发布预告片(16:9) | 15-25s | 7-10 | 骨架 B |
| 产品讲解视频(16:9) | 30-60s | 10-18 | 骨架 C |
| 电影感标题片(16:9) | 45-90s | 7-12 | 骨架 D |
复制骨架(见下方第 7 节),然后立即填充 :root CSS 自定义属性:
:root {
/* === FILL: Your brand identity === */
--bg: #0a0a0d;
--ink: #f5f5f7;
--accent: #7c6cff;
--muted: #5a6270;
--accent-dim: #3d3680;
--font-display: "Space Grotesk", sans-serif;
--font-data: "JetBrains Mono", monospace;
}
避免千篇一律
这些都是所有 LLM 都会优先选择的默认项。请选择真正符合需求说明的方案:
- 禁用字体: Inter、Inter Tight、Roboto、Open Sans、Noto Sans、Lato、Poppins、Outfit、Sora、Fraunces、Playfair Display、Cormorant Garamond、EB Garamond、Syne、Cinzel、Prata、Bodoni Moda、Nunito、Source Sans、PT Sans、Arimo。
- 禁用字体搭配: Fraunces + JetBrains Mono、Inter + 任意字体、Playfair + Lato。
- 质疑这些默认项: 渐变文字、深色背景配青色、纯
#000/#fff、一模一样的卡片网格、左侧边缘强调条、所有内容都居中且权重相同。
选择一组风格鲜明的字体搭配。字重对比必须明显(300 对 900,而不是 400 对 700)。视频字号:标题至少 60px,正文至少 20px,标签至少 16px。
第 3 步:填充场景——内容 + 动画
检查点: 每个场景都有可见内容、至少 2 种第 8 节所述的动画模式,以及场景中段的动态效果。不能有静态场景。
逐个处理场景。每个场景:
3a. 填充场景内容
将文本、图像和布局放入 .scene-content 包装元素中。骨架中已包含该包装元素——请在其中添加元素。
<div class="scene-content">
<h1 id="s3-title" class="display">$1.9 Trillion</h1>
<p id="s3-sub" class="body-text">processed annually</p>
<div id="s3-bar-chart">...</div>
</div>
将装饰元素(光效、颗粒、暗角)放在 .scene-content 外部,直接放入场景 div 中。
3b. 填充入场动画
在标记为当前场景的时间轴代码块中,添加 tl.from() 补间动画。将动画对象从屏幕外/不可见状态变为 CSS 中的位置:
// === SCENE 3 ===
tl.from("#s3-title", { y: 40, autoAlpha: 0, duration: 0.6, ease: "power3.out" }, 10.3);
tl.from("#s3-sub", { y: 20, autoAlpha: 0, duration: 0.5, ease: "power2.out" }, 10.7);
tl.from(
"#s3-bar-chart",
{ scaleY: 0, transformOrigin: "bottom", duration: 0.8, ease: "expo.out" },
11.0,
);
将第一个补间动画的开始时间延后 0.1-0.3s。延迟为零的入场动画会让人感觉像跳切。
3c. 填充场景中的动态效果(这是视频区别于幻灯片的关键)
每个可见元素在入场后都必须继续运动。静态背景上的静态元素就像一张带进度条的 JPEG。每个场景至少使用第 8 节中的 2 种模式。
| 元素 | 场景中的动态效果 | 第 8 节中的模式 |
|---|---|---|
| 统计数据 / 数字 | 计数器从 0 动画递增至目标值 | 计数器动画 |
| SVG 线条 / 路径 | 实时绘制自身 | SVG 描边绘制 |
| 标题 / 字标 | 字符逐个入场 | 字符交错入场 |
| Logo / 标识组合 | 轻微上下漂移 | 呼吸式浮动 |
| 图表 / 条形图 | 条形依次填充 | 条形图填充 |
| 图像 / 截图 | 缓慢缩放:scale: 1 -> 1.03 | Ken Burns(直接使用 tl.to(el, { scale: 1.03, duration: sceneLength, ease: "none" })) |
| 强调色 / 高亮 | 扫过文字 | 高亮扫过 |
| 背景光晕 | 不透明度脉冲变化 | tl.to(".glow", { opacity: 0.6, duration: 1.5, ease: "sine.inOut", yoyo: true, repeat: 1 }) |
**每个场景的最低要求:**入场补间动画 + 至少一种连续动态效果(浮动、计数、缩放或光晕)。包含统计数据或图表的场景应始终使用计数器或条形填充模式——这些效果最具视觉吸引力,也最容易实现。
3d. 调整场景时长
骨架中的时长是占位值。请根据以下内容调整每个场景的 data-duration:
- **阅读时间:**统计显示文本的字数,并参考下方的时长预算
- 最后一个可读元素必须在场景时长过半前完成入场
| 显示文本 | 最短时长 |
|---|---|
| 无文本(主视觉、图标) | 1.5-2s |
| 1-3 个词(引导语、数字) | 2-3s |
| 4-10 个词(标题 + 副标题) | 3-4s |
| 11-20 个词(一两句话) | 4-6s |
| 21-35 个词(一段文字) | 6-8s |
| 35 个词以上 | 拆分为两个场景 |
硬性上限:每个场景 5s,除非你能说明具体原因(主视觉停留、电影感推镜、较长的计数器动画)。
更改场景时长时,请更新后续场景的 data-start,以保持场景首尾相接。还要更新根元素的 data-duration,使其与总时长一致。
调整缓动效果
每个场景至少使用 3 种不同的缓动效果。不要默认所有动画都使用 power2.out。
| 感觉 | 缓动效果 | 时长 |
|---|---|---|
| 平滑 | power2.out | 0.4-0.6s |
| 利落 | power4.out | 0.2-0.3s |
| 弹跳 | back.out(1.6) | 0.3-0.5s |
| 戏剧性 | expo.out | 0.3-0.5s |
| 梦幻 | sine.inOut | 0.5-0.8s |
| 机械 | steps(5) | 0.3-0.5s |
第 4 步:转场
专业规则:大多数切换都采用硬切
在专业视频中,约 95% 的场景切换都是硬切。特效转场(着色器、叠化)仅用于 2-3 个关键时刻——主角亮相、能量转变、CTA 落点。每次切换都用着色器,就像把一段文字里的每个词都加粗一样。
骨架预先设置了在关键时刻使用 2 个着色器转场,其他地方全部硬切。这样节奏会更丰富:切-切-着色器-切-切-着色器-切。
三种转场类型
硬切(默认——大多数场景都使用): 无需转场代码。场景 N 消失,场景 N+1 出现。新场景的入场动画负责所有视觉效果。这是专业视频的默认做法。
着色器转场(每个视频使用 2-3 次——用于主角亮相/高潮/CTA 时刻): 骨架已在关键位置预先设置。HyperShader 会将两个场景捕获为纹理,并通过 WebGL 逐像素合成。
何时使用着色器,何时使用硬切:
| 使用着色器的场景 | 使用硬切的场景 |
|---|---|
| 主角亮相 / 产品揭晓 | 功能之间的衔接场景 |
| 能量显著转变或章节转换 | 快速呈现的列表或统计数据 |
| CTA / 最后的品牌时刻 | 连续 3 个以上快速场景切换 |
| 音乐强调的任何时刻 | 需要营造快速节奏感的场景 |
经验法则:6-8 个场景的视频适合使用2 个着色器转场,其余全部硬切。
调整着色器转场
更改着色器名称——从以下 14 个名称中选择:
domain-warp、ridged-burn、whip-pan、sdf-iris、ripple-waves、gravitational-lens、cinematic-zoom、chromatic-split、swirl-vortex、thermal-distortion、flash-through-white、cross-warp-morph、light-leak、glitch
根据能量匹配着色器:
| 能量 | 着色器 |
|---|---|
| 平静、编辑感 | cross-warp-morph、light-leak、domain-warp |
| 中等、专业 | cinematic-zoom、whip-pan、sdf-iris |
| 高强度、激进 | glitch、chromatic-split、ridged-burn |
| 空灵、神秘 | gravitational-lens、ripple-waves、swirl-vortex |
调整转场时长——更改场景时长后,重新计算每个转场的 time:
transition.time = scene_boundary - (transition.duration / 2)
示例:scene-3 在 8s 结束,转场时长为 0.5s -> time: 7.75。
转场时长不得少于 0.3s。 最佳时长为 0.5s。
骨架如何处理这些情况
骨架只在 HyperShader.init() 中列出锚点场景(即衔接着着色器转场的场景)。锚点场景使用 style="opacity:0;",因为 HyperShader 会管理它们的不透明度。非锚点场景使用 style="visibility:hidden;"。
关键——如果不处理,以下两个错误会导致“中间场景不可见”:
-
非锚点场景需要显式设置
tl.set可见性切换。 如果不设置,场景容器会保持visibility:hidden,子动画则会在不可见的父级中播放。 -
每个着色器组中的第一个锚点场景需要设置
tl.set("#sN", { opacity: 1 }, <start-time>)。 HyperShader 浏览器模式不会自动显示第一个锚点。它在整个时间窗口内都会保持opacity:0。每个 demov4 合成都会出现这个错误。
骨架会为每个非锚点场景预先设置这些切换,使用的是 autoAlpha(而非 visibility):
// --- Non-anchor scene toggles (REQUIRED — must use autoAlpha, not visibility) ---
tl.set("#s1", { autoAlpha: 0 }, 2.5); // hide s1 at its end time
tl.set("#s2", { autoAlpha: 1 }, 2.5); // show s2 at its start
tl.set("#s2", { autoAlpha: 0 }, 5.0); // hide s2 at its end
tl.set("#s3", { autoAlpha: 1 }, 5.0); // show s3 at its start
tl.set("#s3", { autoAlpha: 0 }, 7.5); // hide s3 at its end
为什么用 autoAlpha,而不是 visibility: 每当触发着色器转场时,HyperShader 都会将所有 .scene 元素设为 opacity:0。如果非锚点场景只切换 visibility,这个全局重置就会影响它的 opacity——场景会变为 visibility:visible,但 opacity:0(仍不可见)。autoAlpha 会在一次调用中同时设置 opacity 和 visibility,覆盖这个全局重置。
规则:
- 每个非锚点场景都要添加
tl.set("#sN", { autoAlpha: 1 }, <data-start>)和tl.set("#sN", { autoAlpha: 0 }, <data-start + data-duration>) - 场景 1 只需在结束时间设置隐藏(它开始时可见)
- 锚点场景不要添加
autoAlpha切换——它们的不透明度由 HyperShader 管理 - 添加或删除场景时,相应更新这些切换
8 场景视频的示例,其中着色器转场位于 s4→s5 和 s7→s8:
- 锚点场景:s4、s5、s7、s8(列在 HyperShader 的
scenes数组中,使用opacity:0) - 非锚点场景:s1、s2、s3、s6(不在 HyperShader 中,使用
visibility:hidden,并显式添加tl.set切换) - 场景 1 没有内联样式(从 t=0 起可见)
添加或删除着色器转场
要在两个场景之间添加着色器转场:
- 将两个场景 ID 都添加到
HyperShader.init()中的scenes数组 - 将转场对象添加到
transitions数组 - 将两个场景的样式都从
visibility:hidden改为opacity:0 - 不变量:
scenes.length === transitions.length + 1
要删除着色器转场(改为硬切):
- 从
scenes中移除场景 ID(除非它们也是其他转场的锚点) - 从
transitions中移除该转场 - 将受影响场景的样式从
opacity:0改为visibility:hidden
禁止:不可见的桥接转场。 绝不要用 0.01s 的 flash-through-white 填充。
步骤 5:验证预览并交付
验收标准: 预览从头到尾都能播放。所有场景均可见。没有闪烁。文字清晰可读。
在预览窗格中验证
逐一检查每个场景:
- 场景 1 是否立即出现?(如果是黑屏:运行时未加载,或
__timelines键不匹配) - 着色器转场是否流畅触发?(如果闪烁:转场太短,或退出动画先于转场发生)
- 所有文字在背景上是否清晰可读?
- 每个场景在停留期间是否都有动态效果?(如果静止:缺少场景中段的动态效果)
- 动画是否按正确顺序播放?
故障排查:预览画面全黑
| 症状 | 原因 | 修复方法 |
|---|---|---|
| 全黑 | 运行时脚本缺失或顺序错误 | 检查 GSAP 是否在运行时脚本之前加载到 <head> 中 |
| 全黑 | __timelines 键与 data-composition-id 不匹配 | 两者都必须是 "main" |
| 全黑 | preview.html 中未转发令牌 | 检查是否将 location.search 附加到 src |
| 场景未出现 | data-start / data-duration 错误 | 检查场景时间窗口是否首尾相接 |
| 转场前闪烁 | 着色器触发前播放了退出动画 | 移除退出补间动画——着色器本身就是退出效果 |
| 转场前闪烁 | 转场时长 < 0.3s | 增加到 0.5s |
| 向后定位时显示空白 | 异步捕获竞态条件 | 这是 HyperShader 浏览器模式中的已知错误。向前定位通常可正常工作。若要可靠地拖动预览,请下载并在本地运行 npx hyperframes preview |
| 中间场景不可见 | 未显示首个着色器锚点 | 在每个着色器组的第一个锚点处添加 tl.set("#sN", { opacity: 1 }, startTime) |
| 中间场景不可见 | 非锚点使用了 visibility 而不是 autoAlpha | 改为 tl.set("#sN", { autoAlpha: 1 }, start) 和 tl.set("#sN", { autoAlpha: 0 }, end)。着色器的全局重置会破坏 opacity;仅使用 visibility 无法修复。 |
交付内容
请提供:index.html、preview.html、README.md 和 DESIGN.md。
preview.html 和 README.md 已包含在骨架中——不要修改 preview.html。根据你的 :root 自定义属性生成 DESIGN.md,作为参考文档。
在最终消息中告知用户:
- 构建内容——场景数量、时长、视觉风格概述、使用的着色器转场
- 下一步操作——下载 ZIP,并在本地运行
npx hyperframes preview,以可靠地播放完整合成内容 - 在 Claude Code 中完善的内容——具体说明哪些场景需要优化动画、哪些地方可以收紧节奏、哪些场景中的活动较基础且可以丰富。不要只说“在 Claude Code 中完善”——要说“场景 4 的计数器动画可以通过延长时长变得更流畅,场景 6 则可以为徽标增加轻柔的浮动效果。”
- 注意事项——占位素材、未经核实的统计数据、受真实品牌启发的元素
第 6 节:不可违反的规则
骨架代码会处理大多数结构规则。以下是骨架代码无法强制执行的运行时规则:
确定性(不可妥协)
| 绝不使用 | 改用 |
|---|---|
Math.random() | 有种子的伪随机数生成器(仅在需要随机性时使用) |
Date.now()、performance.now() | 硬编码时间,或在 onUpdate 中使用 tl.time() |
setInterval、setTimeout | 时间线补间 + onUpdate |
repeat: -1 | repeat: Math.ceil(duration / cycle) - 1 |
stagger: { from: "random" } | from: "start"、"center"、"end" |
| 异步构建时间线 | 页面加载时同步构建 |
媒体规则
| 绝不使用 | 改用 |
|---|---|
video.play()、audio.play() | 由框架控制播放 |
不带 muted 的 <video> | 始终使用 muted playsinline |
<video> 上的音频 | 单独的 <audio> 元素 |
| Base64 媒体 | 文件引用或 HTTPS URL |
| 占位符 URL(placehold.co) | 真实素材 |
动画规则
| 绝不使用 | 改用 |
|---|---|
| 着色器转场前的退出补间 | 着色器本身就是退出效果——内容保持可见 |
对场景容器使用 tl.set / tl.to | 由 HyperShader 控制场景透明度 |
requestAnimationFrame | GSAP 补间 |
| 选择器中的模板字面量 | 硬编码字符串 |
使用 CSS transform 居中 | 在包装元素上使用 Flexbox 居中 |
SVG 滤镜 data:image/svg+xml 颗粒效果 | CSS radial-gradient 颗粒效果(见下方模式) |
对 visibility / display 做动画 | 使用 autoAlpha |
自查清单
交付前运行检查。依据实际代码检查,而不是凭假设。
结构有效性(必须通过——Claude Code 无法轻松修复这些问题):
- 每个场景都有
class="scene clip"和所有 data 属性 - 每个场景都有
<div class="scene-content">包装元素 - 锚点场景有
style="opacity:0;"。非锚点场景有style="visibility:hidden;" - 每个非锚点场景都有包含
autoAlpha的tl.set(不是visibility)。开始时autoAlpha: 1,结束时autoAlpha: 0。 - 每个着色器组中的首个锚点场景都有
tl.set("#sN", { opacity: 1 }, startTime)。否则该场景会保持不可见。 - 场景时间窗口首尾相接(没有间隙)
- 着色器转场边界位于时间窗口内:
time < boundary < time + duration - 转场时长不短于 0.3s
- 除最后一个场景外,没有退出补间
- 没有
Date.now()、未使用种子的Math.random()、repeat: -1 - 没有将 SVG 滤镜数据 URL 用作
background-image -
window.__timelines["main"] = tl与data-composition-id相匹配
品牌与内容准确性(你的核心工作——务必做到):
- 颜色与简报 / 附件完全一致
- 不使用禁用字体
- 最小字号:标题 60px 以上,正文 20px 以上,标签 16px 以上
- 数字列使用
font-variant-numeric: tabular-nums - 每个场景都有有意义的内容(不是占位文本)
- 场景数量和时长与视频类型相匹配
动画基线(足以开始——Claude Code 会进一步润色):
- 每个场景至少有一个入场补间(
tl.from) - 每个超过 4s 的场景至少有一处场景中活动(浮动、计数、发光)
- 没有完全静止的场景(完全没有补间)
- 场景文字在限定时间内清晰可读
第 7 节:骨架代码
preview.html(通用——所有视频类型均原样复制)
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>HyperFrames Preview</title>
<style>
html,
body {
margin: 0;
padding: 0;
background: #111;
height: 100%;
overflow: hidden;
}
</style>
<script type="module" src="https://cdn.jsdelivr.net/npm/@hyperframes/player"></script>
</head>
<body>
<hyperframes-player
id="p"
controls
autoplay
muted
style="display:block;width:100vw;height:100vh"
></hyperframes-player>
<script>
document.getElementById("p").setAttribute("src", "./index.html" + location.search);
</script>
</body>
</html>
README.md(通用——替换 <project-name>)
# <project-name>
A HyperFrames video composition. Plain HTML + GSAP; rendered to MP4 by the `hyperframes` CLI.
## Requirements
- **Node.js 22+** -- [nodejs.org](https://nodejs.org/)
- **FFmpeg** -- `brew install ffmpeg` (macOS) or `sudo apt install ffmpeg` (Debian/Ubuntu) or [ffmpeg.org/download](https://ffmpeg.org/download.html) (Windows)
Verify: `npx hyperframes doctor`
## Preview
```bash
npx hyperframes preview
```
Opens the HyperFrames Studio at `http://localhost:3002` with frame-accurate scrubbing.
## Refine with Claude Code
This project was drafted in Claude Design. To polish animations, timing, and pacing:
```bash
npx skills add heygen-com/hyperframes # install HyperFrames skills (one-time)
npx hyperframes lint # verify structure (should pass with zero errors)
npx hyperframes preview # open the studio for live feedback
```
Then open in Claude Code and iterate:
- "Make scene 3's entrance snappier"
- "Add a counter animation to the stat in scene 5"
- "Tighten the pacing -- scenes 4 and 6 feel too long"
- "Change the shader on transition 3 to glitch"
## Render
```bash
npx hyperframes render index.html -o output.mp4
```
1920x1080 / 30fps by default. Use `--fps 60` or `--resolution 3840x2160` to override.
骨架 A——社交短视频(1080x1920,15s,6 个场景)
转场计划:s1→s2 硬切,s2→s3 硬切,s3→s4 着色器(主角揭晓),s4→s5 硬切,s5→s6 硬切。中点使用一个着色器。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1080, height=1920" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@hyperframes/core/dist/hyperframe.runtime.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@hyperframes/shader-transitions/dist/index.global.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;500;700&family=JetBrains+Mono:wght@400&display=swap"
rel="stylesheet"
/>
<style>
:root {
/* === FILL: Your brand identity === */
--bg: #0a0a0d;
--ink: #f5f5f7;
--accent: #7c6cff;
--muted: #5a6270;
--accent-dim: #3d3680;
--font-display: "Space Grotesk", sans-serif;
--font-data: "JetBrains Mono", monospace;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
width: 1080px;
height: 1920px;
overflow: hidden;
background: var(--bg);
color: var(--ink);
}
.scene {
position: absolute;
top: 0;
left: 0;
width: 1080px;
height: 1920px;
overflow: hidden;
}
.scene-content {
width: 100%;
height: 100%;
padding: 120px 80px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 24px;
box-sizing: border-box;
position: relative;
z-index: 1;
}
.clip {
}
.display {
font-family: var(--font-display);
font-weight: 700;
line-height: 1.1;
}
.body-text {
font-family: var(--font-display);
font-weight: 300;
line-height: 1.4;
color: var(--muted);
}
.data-text {
font-family: var(--font-data);
font-weight: 400;
font-variant-numeric: tabular-nums;
}
.grain {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 50;
opacity: 0.18;
background-image:
radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1.2px),
radial-gradient(rgba(0, 0, 0, 0.18) 1px, transparent 1.2px);
background-size:
3px 3px,
5px 5px;
background-position:
0 0,
1px 2px;
mix-blend-mode: overlay;
}
/* === FILL: Per-scene styles below === */
</style>
</head>
<body>
<div
id="main"
data-composition-id="main"
data-width="1080"
data-height="1920"
data-start="0"
data-duration="15"
>
<div class="scene clip" id="s1" data-start="0" data-duration="2.5" data-track-index="0">
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
<div
class="scene clip"
id="s2"
data-start="2.5"
data-duration="2.5"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
<div
class="scene clip"
id="s3"
data-start="5"
data-duration="2.5"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
<div
class="scene clip"
id="s4"
data-start="7.5"
data-duration="2.5"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
<div
class="scene clip"
id="s5"
data-start="10"
data-duration="2.5"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
<div
class="scene clip"
id="s6"
data-start="12.5"
data-duration="2.5"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="scene-content">
</div>
</div>
</div>
<script>
window.__timelines = window.__timelines || {};
var tl = gsap.timeline({ paused: true });
// --- Non-anchor scene toggles (REQUIRED — use autoAlpha) ---
tl.set("#s1", { autoAlpha: 0 }, 2.5);
tl.set("#s2", { autoAlpha: 1 }, 2.5);
tl.set("#s2", { autoAlpha: 0 }, 5.0);
// s3, s4 are shader anchors — HyperShader manages their opacity
tl.set("#s3", { opacity: 1 }, 5.0); // first anchor must be explicitly shown
tl.set("#s5", { autoAlpha: 1 }, 10.0);
tl.set("#s5", { autoAlpha: 0 }, 12.5);
tl.set("#s6", { autoAlpha: 1 }, 12.5);
// === SCENE 1 (0-2.5s) — hook ===
// FILL: entrance + mid-scene activity (use 2+ patterns from Section 8)
// === SCENE 2 (2.5-5s) ===
// FILL: entrance + mid-scene activity
// === SCENE 3 (5-7.5s) — SHADER ANCHOR, no exit tweens ===
// FILL: entrance + mid-scene activity
// === SCENE 4 (7.5-10s) — hero (shader reveals this) ===
// FILL: entrance + mid-scene activity
// === SCENE 5 (10-12.5s) — proof ===
// FILL: entrance + mid-scene activity
// === SCENE 6 (12.5-15s) — CTA, final scene, exit OK ===
// FILL: entrance + mid-scene activity + optional exit
// --- Shader: 1 transition at the hero reveal ---
window.HyperShader.init({
bgColor:
getComputedStyle(document.documentElement).getPropertyValue("--bg").trim() || "#0a0a0d",
scenes: ["s3", "s4"],
timeline: tl,
transitions: [{ time: 7.25, shader: "cinematic-zoom", duration: 0.5 }],
});
window.__timelines["main"] = tl;
</script>
</body>
</html>
骨架 B——发布预告片(1920x1080,25s,8 个场景)
转场计划:s1→s2 硬切,s2→s3 硬切,s3→s4 硬切,s4→s5 着色器(主角揭晓),s5→s7 着色器(能量转换,s6 作为运行时管理的插播片段播放),s7→s8 着色器(CTA 落版)。7 次切换中有 3 次使用着色器。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1920, height=1080" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@hyperframes/core/dist/hyperframe.runtime.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@hyperframes/shader-transitions/dist/index.global.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;500;700&family=JetBrains+Mono:wght@400&display=swap"
rel="stylesheet"
/>
<style>
:root {
/* === FILL: Your brand identity === */
--bg: #0a0a0d;
--ink: #f5f5f7;
--accent: #7c6cff;
--muted: #5a6270;
--accent-dim: #3d3680;
--font-display: "Space Grotesk", sans-serif;
--font-data: "JetBrains Mono", monospace;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html,
body {
width: 1920px;
height: 1080px;
overflow: hidden;
background: var(--bg);
color: var(--ink);
}
.scene {
position: absolute;
top: 0;
left: 0;
width: 1920px;
height: 1080px;
overflow: hidden;
}
.scene-content {
width: 100%;
height: 100%;
padding: 100px 160px;
display: flex;
flex-direction: column;
justify-content: center;
gap: 24px;
box-sizing: border-box;
position: relative;
z-index: 1;
}
.clip {
}
.display {
font-family: var(--font-display);
font-weight: 700;
line-height: 1.1;
}
.body-text {
font-family: var(--font-display);
font-weight: 300;
line-height: 1.4;
color: var(--muted);
}
.data-text {
font-family: var(--font-data);
font-weight: 400;
font-variant-numeric: tabular-nums;
}
.grain {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 50;
opacity: 0.18;
background-image:
radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1.2px),
radial-gradient(rgba(0, 0, 0, 0.18) 1px, transparent 1.2px);
background-size:
3px 3px,
5px 5px;
background-position:
0 0,
1px 2px;
mix-blend-mode: overlay;
}
.vignette {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 49;
background: radial-gradient(ellipse at center, transparent 50%, rgba(0, 0, 0, 0.4) 100%);
}
/* === FILL: Per-scene styles below === */
</style>
</head>
<body>
<div
id="main"
data-composition-id="main"
data-width="1920"
data-height="1080"
data-start="0"
data-duration="25"
>
<div class="scene clip" id="s1" data-start="0" data-duration="3" data-track-index="0">
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s2"
data-start="3"
data-duration="3"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s3"
data-start="6"
data-duration="3"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s4"
data-start="9"
data-duration="3.5"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s5"
data-start="12.5"
data-duration="3"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s6"
data-start="15.5"
data-duration="3"
data-track-index="0"
style="visibility:hidden;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s7"
data-start="18.5"
data-duration="3"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
<div
class="scene clip"
id="s8"
data-start="21.5"
data-duration="3.5"
data-track-index="0"
style="opacity:0;"
>
<div class="grain"></div>
<div class="vignette"></div>
<div class="scene-content"></div>
</div>
</div>
<script>
window.__timelines = window.__timelines || {};
var tl = gsap.timeline({ paused: true });
// --- Non-anchor scene visibility toggles (REQUIRED) ---
tl.set("#s1", { autoAlpha: 0 }, 3.0);
tl.set("#s2", { autoAlpha: 1 }, 3.0);
tl.set("#s2", { autoAlpha: 0 }, 6.0);
tl.set("#s3", { autoAlpha: 1 }, 6.0);
tl.set("#s3", { autoAlpha: 0 }, 9.0);
// --- First shader anchor must be explicitly shown ---
tl.set("#s4", { opacity: 1 }, 9.0);
// s4, s5 are shader anchors — HyperShader manages their opacity after transitions
tl.set("#s6", { autoAlpha: 1 }, 15.5);
tl.set("#s6", { autoAlpha: 0 }, 18.5);
// --- Second shader group's first anchor must also be shown ---
tl.set("#s7", { opacity: 1 }, 18.5);
// s7, s8 are shader anchors — HyperShader manages their opacity after transitions
// === SCENE 1 (0-3s) — hook ===
// === SCENE 2 (3-6s) — hard cut ===
// === SCENE 3 (6-9s) — hard cut ===
// === SCENE 4 (9-12.5s) — SHADER ANCHOR, no exit tweens ===
// === SCENE 5 (12.5-15.5s) — shader from s4, hero reveal ===
// === SCENE 6 (15.5-18.5s) — hard cut ===
// === SCENE 7 (18.5-21.5s) — SHADER ANCHOR, no exit tweens ===
// === SCENE 8 (21.5-25s) — shader from s7, CTA. Final, exit OK ===
// --- Shader transitions: 2 key moments ---
// s4->s5 (hero reveal) and s7->s8 (CTA landing)
// HyperShader requires consecutive anchors, so we use two groups:
// Group 1: [s4, s5] with 1 transition
// Group 2: [s7, s8] with 1 transition
// But HyperShader only supports one init() call, so we chain them:
// [s4, s5] — shader — then runtime hard-cuts s5->s6->s7 — then [s7, s8]
// To satisfy the invariant with one init(), we include s5->s7 gap scenes.
// Simplest: just use one contiguous anchor block [s4, s5, s7, s8] with
// the s5->s7 transition as a real (visible) shader too. This gives you
// 3 shaders total — still well under the "every cut" anti-pattern.
window.HyperShader.init({
bgColor:
getComputedStyle(document.documentElement).getPropertyValue("--bg").trim() || "#0a0a0d",
scenes: ["s4", "s5", "s7", "s8"],
timeline: tl,
transitions: [
{ time: 12.25, shader: "cinematic-zoom", duration: 0.5 },
{ time: 15.25, shader: "light-leak", duration: 0.5 },
{ time: 21.25, shader: "cross-warp-morph", duration: 0.5 },
],
});
window.__timelines["main"] = tl;
</script>
</body>
</html>
骨架 C——产品解说视频(1920x1080,45s,12 个场景)
沿用骨架 B 的结构,但使用 12 个场景 div(s1-s12),data-duration 总计为 45s,并包含 11 次转场。根据内容密度调整场景时长:混合使用 3s、3.5s、4s 和 5s 的场景。场景节奏示例:3-3-4-3.5-4-5-3.5-4-3.5-4-4-3.5。
骨架 D——电影感标题(1920x1080,60s,7 个场景)
沿用相同结构,使用 7 个场景 div(s1-s7),延长场景时长(每个 6-10s),减少转场(6 次),并更克制地使用着色器(cross-warp-morph、thermal-distortion)。场景节奏:8-7-8-10-9-10-8。
第 8 节:常见动画模式
复制粘贴以下代码。这些模式会出现在每个生产级合成中。
计数器动画
var counterObj = { v: 0 };
tl.to(
counterObj,
{
v: 1900000000000,
duration: 2.0,
ease: "power2.out",
onUpdate: function () {
document.getElementById("s3-stat").textContent = "$" + (counterObj.v / 1e12).toFixed(1) + "T";
},
},
10.5,
);
SVG 描边绘制
<svg viewBox="0 0 400 200" style="position:absolute; bottom:100px; left:160px;">
<path
id="s2-line"
d="M 0 100 Q 200 20 400 100"
stroke="var(--accent)"
stroke-width="3"
fill="none"
stroke-linecap="round"
stroke-dasharray="440"
stroke-dashoffset="440"
/>
</svg>
tl.to("#s2-line", { strokeDashoffset: 0, duration: 1.0, ease: "power2.out" }, 3.5);
字符错开动画
<h1 class="display" style="font-size:120px;">
<span class="char">N</span><span class="char">O</span><span class="char">R</span>
<span class="char">T</span><span class="char">H</span>
</h1>
tl.from(
".char",
{
y: 60,
autoAlpha: 0,
duration: 0.5,
ease: "power3.out",
stagger: { each: 0.12, from: "start" },
},
29.5,
);
呼吸式浮动(场景中的动态效果)
tl.to(
"#s4-logo",
{
y: -5,
duration: 1.5,
ease: "sine.inOut",
yoyo: true,
repeat: 1,
},
15.0,
);
条形图填充
["#bar1", "#bar2", "#bar3", "#bar4"].forEach(function (sel, i) {
tl.from(
sel,
{
scaleY: 0,
transformOrigin: "bottom",
duration: 0.6,
ease: "expo.out",
},
11.0 + i * 0.15,
);
});
环绕 / 旋转
tl.to(
"#orbit-dot",
{
rotation: 360,
duration: 3.0,
ease: "none",
transformOrigin: "50% 200px",
},
8.5,
);
高光扫过(background-size 动画)
#s5-headline {
background: linear-gradient(var(--accent), var(--accent)) no-repeat 0 85% / 0% 30%;
}
tl.to("#s5-headline", { backgroundSize: "100% 30%", duration: 0.6, ease: "power2.out" }, 22.0);
CSS radial-gradient 颗粒效果(兼容 Safari + Claude Design iframe)
.grain {
position: absolute;
inset: 0;
pointer-events: none;
z-index: 50;
opacity: 0.18;
background-image:
radial-gradient(rgba(255, 255, 255, 0.08) 1px, transparent 1.2px),
radial-gradient(rgba(0, 0, 0, 0.18) 1px, transparent 1.2px);
background-size:
3px 3px,
5px 5px;
background-position:
0 0,
1px 2px;
mix-blend-mode: overlay;
}
绝不要使用 SVG filter data:image/svg+xml 颗粒效果——它会污染 Safari 中的 html2canvas,导致 Claude Design 跨域 iframe 中的所有着色器转场失效。
参考资料(仅在需要时获取)
以上已内联所有关键信息。以下资料适用于特殊情况:
- 核心合成规范(data 属性、子组合接线):https://github.com/heygen-com/hyperframes/blob/main/skills/hyperframes/SKILL.md
- 动效理论(将缓动视为情感表达、方向规则):https://github.com/heygen-com/hyperframes/blob/main/skills/hyperframes/references/motion-principles.md
- 排版(完整禁用列表、字重对比、OpenType):https://github.com/heygen-com/hyperframes/blob/main/skills/hyperframes/references/typography.md
- 转场(着色器目录、CSS 转场模式):https://github.com/heygen-com/hyperframes/blob/main/skills/hyperframes/references/transitions.md
- 与音频同步的字幕:https://github.com/heygen-com/hyperframes/blob/main/skills/hyperframes/references/captions.md
- 完整文档:https://hyperframes.heygen.com/