@hyperframes/player
"@hyperframes/player"
player 包提供了一个 <hyperframes-player> 自定义元素,可以在任何地方嵌入 HyperFrames 合成 — 适用于任何框架或纯 HTML。零依赖,gzip 后仅 3KB。
npm install @hyperframes/player
何时使用
在以下场景使用 @hyperframes/player:
- 在网站、仪表盘或应用中嵌入渲染后的合成
- 在落地页或产品演示中添加类似视频的播放器
- 在文档或博客文章中展示合成
如果需要以下功能,请使用其他包:
快速开始
通过 CDN
<script type="module" src="https://cdn.jsdelivr.net/npm/@hyperframes/player"></script>
<hyperframes-player
src="./my-composition/index.html"
controls
autoplay
muted
style="width: 100%; max-width: 800px; aspect-ratio: 16/9"
></hyperframes-player>
如果需要使用传统 <script> 标签而非 ESM,可以使用显式的全局构建版本:
<script src="https://cdn.jsdelivr.net/npm/@hyperframes/player/dist/hyperframes-player.global.js"></script>
通过 npm
import '@hyperframes/player';
<hyperframes-player src="/compositions/intro.html" controls></hyperframes-player>
HTML 属性
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
src | string | 必需 | 合成 HTML 的 URL 或相对路径 |
width | number | 1920 | 合成宽度(像素) |
height | number | 1080 | 合成高度(像素) |
controls | boolean | false | 显示播放控制覆盖层 |
autoplay | boolean | false | 加载后自动播放 |
loop | boolean | false | 循环播放 |
muted | boolean | true | 静音音频(大多数浏览器自动播放时需要) |
poster | string | — | 首次播放前显示的图片 URL |
playback-rate | number | 1 | 播放速度倍率 |
JavaScript API
player 镜像了原生 <video> 元素的 API:
const player = document.querySelector('hyperframes-player');
// 播放控制
player.play();
player.pause();
player.seek(2.5); // 跳转到 2.5 秒
// 属性
player.currentTime; // number — 当前位置(秒)
player.currentTime = 5; // 跳转到 5 秒
player.duration; // number — 总时长
player.paused; // boolean
player.ready; // boolean — 合成加载后为 true
player.playbackRate; // number — 获取/设置速度
player.muted; // boolean — 获取/设置静音
player.loop; // boolean — 获取/设置循环
事件
const player = document.querySelector('hyperframes-player');
player.addEventListener('ready', (e) => {
console.log('Duration:', e.detail.duration);
});
player.addEventListener('timeupdate', (e) => {
console.log('Time:', e.detail.currentTime);
});
player.addEventListener('play', () => console.log('Playing'));
player.addEventListener('pause', () => console.log('Paused'));
player.addEventListener('ended', () => console.log('Ended'));
player.addEventListener('error', (e) => console.error(e.detail.message));
| 事件 | Detail | 描述 |
|---|---|---|
ready | { duration } | 合成已加载并发现时间轴 |
timeupdate | { currentTime } | 播放期间触发(约 30fps) |
play | — | 播放已开始 |
pause | — | 播放已暂停 |
ended | — | 播放已到达末尾 |
error | { message } | 加载或运行时错误 |
框架示例
React
import '@hyperframes/player';
function VideoPreview({ src }) {
return (
<hyperframes-player
src={src}
controls
style=""
/>
);
}
Vue
<template>
<hyperframes-player :src="compositionUrl" controls />
</template>
<script setup>
import '@hyperframes/player';
const compositionUrl = './compositions/intro.html';
</script>
编程方式
import '@hyperframes/player';
const player = document.createElement('hyperframes-player');
player.src = './my-composition/index.html';
player.controls = true;
player.addEventListener('ready', () => player.play());
document.getElementById('player-container').appendChild(player);
进阶:iframe 访问
合成运行在 player Shadow DOM 容器内的沙盒 <iframe> 中。对于大多数用例,你不需要直接访问 — 上面的 JavaScript API 和事件已经足够。但如果你正在构建编辑器、录制器或基于 player 的自定义时间轴,就需要检查合成的 DOM 或读取其 __player / __timelines 运行时对象。iframeElement getter 暴露了内部 iframe 供这些消费者使用:
const player = document.querySelector('hyperframes-player');
const iframe = player.iframeElement;
// 访问合成的 DOM
iframe.contentDocument.querySelectorAll('[data-composition-id]');
// 读取运行时(GSAP 时间轴、元素注册表等)
iframe.contentWindow.__timelines;
这是将 player 桥接到编辑器工具(如 @hyperframes/studio)的规范方式。studio 导出了一个 resolveIframe 辅助函数,它能同时处理直接 iframe 引用和 web 组件引用:
import { useTimelinePlayer, resolveIframe } from '@hyperframes/studio';
const { iframeRef } = useTimelinePlayer();
const player = document.createElement('hyperframes-player');
player.setAttribute('src', src);
container.appendChild(player);
// 转发内部 iframe,使 useTimelinePlayer 可以驱动 play/pause/seek。
iframeRef.current = resolveIframe(player);
React:声明式 ref 模式
如果你更喜欢 JSX 而非命令式元素创建,可以将 ref 附加到 web 组件并在 effect 中解析 iframe:
import '@hyperframes/player';
import type { HyperframesPlayer } from '@hyperframes/player';
import { useTimelinePlayer, resolveIframe } from '@hyperframes/studio';
function StudioPreview({ src }: { src: string }) {
const { iframeRef, onIframeLoad } = useTimelinePlayer();
const playerRef = useRef<HyperframesPlayer>(null);
useEffect(() => {
iframeRef.current = resolveIframe(playerRef.current);
});
return (
<hyperframes-player
ref={playerRef}
src={src}
onLoad={onIframeLoad}
/>
);
}
⚠️ Warning
常见问题 — 如果你将
<hyperframes-player>元素本身(而非iframeElement)传入期望<iframe>的 hook 或 API,所有.contentWindow/.contentDocument访问都会返回null,因为 iframe 位于 player 的 Shadow DOM 内部。时间轴跳转、播放、暂停和 DOM 检查都会静默地不执行任何操作。始终先提取iframeElement,或使用@hyperframes/studio的resolveIframe,它能透明地处理 iframe 和 web 组件宿主。
架构
player 在 Shadow DOM 容器内使用 iframe。这提供了:
- 隔离 — 合成的 CSS/JS 不会泄漏到或冲突于你的页面
- 安全 — iframe 沙箱限制了合成的能力
- 缩放 — 通过 CSS 变换自动缩放合成以适应 player 的容器
player 通过 HyperFrames 运行时桥接协议(postMessage)与合成通信。现有的合成无需修改即可工作。
控件
当存在 controls 属性时,底部会出现一个最小化的覆盖层:
- 播放/暂停 按钮(左侧)
- 进度条 支持拖动(鼠标 + 触控)
- 时间显示 显示当前时间 / 总时长(右侧)
- 3 秒不活动后自动隐藏,悬停时重新出现