核心概念

帧适配器

将你自己的动画运行时引入 Hyperframes。

帧适配器(Frame Adapter)模式是 Hyperframes 支持多种动画运行时的方式。每个适配器需要回答的核心问题是:

在第 N 帧时,屏幕应该是什么样子?

如果一个运行时能回答这个问题,它就可以接入 Hyperframes。

适配器 API 当前处于 **v0**(实验性)阶段。在 v1 之前可能会有破坏性变更。核心契约(按帧定位、确定性输出)是稳定的,但方法签名可能会演变。

工作原理

宿主应用(引擎生产器)通过按严格顺序调用适配器方法来驱动渲染。适配器从不控制自己的时钟——它只响应定位命令。

sequenceDiagram
participant Host as 宿主(引擎)
participant Adapter as 帧适配器
participant Chrome as Chrome / 浏览器

Host->>Adapter: init(context)
Adapter-->>Host: 就绪
Host->>Adapter: getDurationFrames()
Adapter-->>Host: 300 帧

loop 遍历每一帧 0..300
Host->>Host: 归一化帧(clamp、floor)
Host->>Adapter: seekFrame(frame)
Adapter->>Chrome: 更新 DOM / canvas 状态
Adapter-->>Host: 完成
Host->>Chrome: 捕获像素缓冲区
end

Host->>Adapter: destroy()
Adapter-->>Host: 清理完成

适配器 API(v0)

ype FrameAdapterContext = {
compositionId: string;
fps: number;
width: number;
height: number;
rootElement?: HTMLElement;
};

ype FrameAdapter = {
id: string;
init?: (ctx: FrameAdapterContext) => Promise<void> | void;
getDurationFrames: () => number;
seekFrame: (frame: number) => Promise<void> | void;
destroy?: () => Promise<void> | void;
};

必须满足的语义

  • getDurationFrames() 必须返回一个 >= 0 的有限整数
  • seekFrame(frame) 必须支持任意顺序的定位(向前、向后、随机)
  • seekFrame(frame) 对于相同的输入帧必须是幂等的
  • seekFrame(frame) 必须将内部时间限制在适配器的范围内
  • 适配器应该是暂停/定位驱动的,而非时钟驱动的

宿主编排

宿主在调用适配器之前会对帧进行归一化:

normalizedFrame = clamp(Math.floor(frame), 0, durationFrames);

典型的渲染循环:

await adapter.init?.({ compositionId, fps, width, height, rootElement });
const durationFrames = adapter.getDurationFrames();

for (let frame = 0; frame <= durationFrames; frame += 1) {
await adapter.seekFrame(frame);
// 捕获该帧的像素缓冲区
}

await adapter.destroy?.();

确定性契约

以下规则对任何适配器来说都是不可协商的。它们是 Hyperframes 确定性渲染保证的基础。

  • 规范时钟:t = frame / fps
  • 无挂钟依赖(Date.now、依赖漂移的逻辑)
  • 无未设种子的随机性
  • 无渲染时网络请求
  • 固定输出参数(fpswidthheight
  • 仅有限时长
  • 在定位前进行确定性帧量化

支持的运行时

官方运行时适配器:

运行时定位方法Skill
GSAPtimeline.totalTime(timeSeconds)timeline.seek(timeSeconds)/gsap
Anime.jsinstance.seek(timeMs),适用于注册在 window.__hfAnime 上的动画/animejs
CSS keyframes浏览器 Animation.currentTime,带暂停的负延迟回退/css-animations
Lottie / dotLottiegoToAndStop(timeMs, false)、原始帧设置器或播放器定位 API/lottie
Three.js / WebGLhf-seek 事件加上 window.__hfThreeTime 用于确定性场景渲染/three
Web Animations APIdocument.getAnimations()animation.currentTime/waapi

欢迎社区贡献适配器——如果它能按帧定位,它就属于 Hyperframes。

一致性测试

每个适配器应通过以下最低测试:

  1. 可重复性 -- 对同一帧定位两次,获得相同的输出
  2. 随机定位 -- 定位顺序 [90, 10, 50, 10] 产生确定性结果
  3. 边界值 -- 负数和溢出帧值不会导致崩溃
  4. 持续时间 -- 返回的持续时间是有限整数
  5. 清理 -- destroy 后没有泄漏的定时器/监听器

下一步