@leexiaohui/vframe-player
v1.0.2
Published
基于 Canvas 的轻量级序列帧图片播放器。以最小 API 提供帧率控制、循环/往返播放、播放区间、预加载与事件钩子,适合产品动效、分镜浏览、3D/AR 截帧预览等场景。
Readme
@leexiaohui/vframe-player
基于 Canvas 的轻量级序列帧图片播放器。以最小 API 提供帧率控制、循环/往返播放、播放区间、预加载与事件钩子,适合产品动效、分镜浏览、3D/AR 截帧预览等场景。
- 纯 TypeScript,零依赖,支持 Tree-shaking
- Canvas 居中缩放,适配不同尺寸图片
- 循环播放(
loop),支持无限循环与次数控制 - 往返播放(
yoyo),前进到尾帧再倒序回到首帧 - 帧率控制(
fps),按时间间隔驱动渲染 - 区间播放(
play(start, end)),快速设置开始/结束帧 - 预加载(
preload),加载完成后回调通知 - 完整事件回调:开始、暂停、完成、半程完成、单次完成、进入每帧…
注:本文档由 AI 辅助编写
安装
# 任选其一
pnpm add @leexiaohui/vframe-player
npm i @leexiaohui/vframe-player
yarn add @leexiaohui/vframe-player快速开始(原生)
<div id="player" style="width:320px;height:504px;position:relative"></div>
<script type="module">
import VFramePlayer from '@leexiaohui/vframe-player';
const player = new VFramePlayer({
dom: document.getElementById('player'), // 必填:容器,用于挂载 Canvas
imgArr: Array.from({ length: 151 }).map(
(_, i) => `https://vmllab-js.github.io/vFramePlayer/image/${i}.jpg`
),
preload: true, // 预加载图片
fps: 60, // 帧率
loop: 0, // 0 表示无限循环
yoyo: false,
autoplay: true,
onPlayStateChange: (isPlaying) => {
console.log('playing:', isPlaying);
},
onLoad: () => console.log('images loaded'),
onComplete: () => console.log('全部播放完成'),
onCompleteOne: () => console.log('完成一次循环'),
onFrameEnter: (frame) => console.log('进入帧:', frame),
});
// 控制示例
// player.pause();
// player.play(10, 40); // 只播放第 10 到 40 帧(含)
// player.goto(100); // 跳转到第 100 帧(0 基)
// player.set('loop', 3); // 设置循环次数为 3 次
// player.set('fps', 24); // 动态修改帧率(即时生效)
</script>在 Vue 中使用(简版)
<template>
<div ref="refPlayer" style="width:320px;height:504px;position:relative" />
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import VFramePlayer from '@leexiaohui/vframe-player';
const refPlayer = ref<HTMLDivElement>();
let instance: VFramePlayer | undefined;
onMounted(() => {
instance = new VFramePlayer({
dom: refPlayer.value,
imgArr: Array.from({ length: 151 }).map(
(_, i) => `https://vmllab-js.github.io/vFramePlayer/image/${i}.jpg`
),
preload: true,
fps: 60,
loop: 1,
});
});
</script>更完整的交互示例请参考仓库内 src/index.example.vue。
API 参考
构造函数
new VFramePlayer(options: VFramePlayerOptions)
VFramePlayerOptions
dom?: HTMLElement- 播放器容器。传入后会在容器内挂载一个绝对定位的 Canvas。
- 强烈建议传入;未传入时 Canvas 不会自动插入文档,画面不可见。
imgArr?: string[]- 图片列表(按顺序播放)。建议统一尺寸以避免缩放导致的抖动。
fps?: number- 帧率,默认 30。按时间间隔驱动渲染,受浏览器与设备性能影响。
loop?: number- 循环次数;
0表示无限循环。默认1。
- 循环次数;
yoyo?: boolean- 往返播放。到达尾帧后按倒序返回首帧,算一次完整循环。
preload?: boolean- 是否在构造时预加载全部图片并创建 Canvas。若未预加载,首次
play()会自动预加载。
- 是否在构造时预加载全部图片并创建 Canvas。若未预加载,首次
autoplay?: boolean- 是否在构造后立即开始播放。
- 事件回调(均可选):
onPlay?: () => void— 开始播放onPaused?: () => void— 暂停播放onEnd?: () => void— 到达最后一次循环的终点onPlayStateChange?: (isPlaying: boolean) => void— 播放状态变化onLoad?: () => void— 预加载完成(图片与 Canvas 就绪)onOptionsChange?: (options) => void— 选项被修改onComplete?: () => void— 播放全部完成onCompleteOne?: () => void— 完成一次完整循环onCompleteHalf?: () => void— 在yoyo模式下到达尾帧的半程完成onFrameEnter?: (frame: number) => void— 进入某一帧(0 基)
方法
play(start?: number, end?: number): void- 开始播放;可传入区间(含起止帧)。若尚未预加载,会先预加载再播放。
pause(): void- 暂停播放,并触发
onPaused。
- 暂停播放,并触发
goto(frame: number): void- 跳转并渲染到指定帧(0 基)。必须位于当前播放区间内。
set<K extends keyof VFramePlayerOptions>(key: K, value: VFramePlayerOptions[K]): void- 动态更新选项,并触发
onOptionsChange。loop与fps均即时生效:在播放中修改fps将在下一帧开始按新帧率推进。
- 动态更新选项,并触发
destroy(): void- 停止播放并清理资源(取消 RAF、移除 Canvas、释放图片引用)。组件/页面卸载时建议调用。
属性
frameCount: number- 总帧数(即
imgArr.length)。
- 总帧数(即
行为细节
- 帧索引为 0 基;UI 场景可自行转换为 1 基展示。
play(start, end)的区间是 闭区间,即包含start与end。yoyo模式下,尾帧触发onCompleteHalf,回到首帧再触发onCompleteOne。- 循环完成最终会触发
onEnd与onComplete。无限循环(loop=0)则不会触发结束。 - Canvas 会根据容器尺寸进行居中缩放,采用
min(widthScale, heightScale)缩放比,避免裁切。
性能与实践建议
- 图片尺寸尽量一致,减少缩放带来的视觉跳变。
- 开启
preload,可避免播放开始时的网络抖动。 - 容器(
dom)需设置固定尺寸;Canvas 将覆盖容器并绝对定位。 - 跨域图片可正常绘制,但若需要导出像素(如
toDataURL),请确保源站开启 CORS。
兼容性
- 依赖
Canvas与requestAnimationFrame,适配现代浏览器。Node 环境不支持直接渲染。
开发与构建
- 构建:
rollup -c输出dist/index.mjs与dist/index.cjs,类型定义dist/index.d.ts。 - 包信息:
sideEffects=false,适配 Tree-shaking。
示例资源
- 示例帧图集来源:
https://vmllab-js.github.io/vFramePlayer/image/{index}.jpg
常见问题(FAQ)
- 画面模糊?确保容器尺寸与期望显示尺寸一致;图片与容器比例差异过大时会发生缩放插值。
- 跳转帧无效?请检查是否超出当前播放区间(
startFrame~endFrame)。
变更日志与反馈
- 问题反馈与需求建议:https://github.com/leexiaohui1997/npm-projects/issues
- 变更记录:按照仓库 Releases/Changesets 发布。
License
MIT © 橙续缘
