custom-svga

A lightweight, tree-shakable SVGA animation player for Vue 3 & modern web. Isomorphic inline worker parsing with main-thread MockWorker fallback, in-flight sprite/text replacement. Zero UI framework deps.(面向 Vue3 与现代浏览器的轻量 SVGA 动画播放器。同构内联 Worker 解析 + 主线程
3,957
Install
npm install custom-svga
Latest Version:2.3.1
License:MIT
Last Updated:Sep 11, 2026
Links: npm
Maintainer: dream_life

custom-svga

轻量、可摇树的 SVGA 动画播放器,面向 Vue3、现代浏览器与移动端。

⭐ 如果这个项目对你有帮助,欢迎在 GitHub 上点亮 Star 支持!

GitHub stars

极致轻量 · 移动端更高效 · 同构内联 Worker 解析 · 动态精灵/文本替换 · 零 UI 框架依赖
  • 同构内联 Worker 解析:真实 Web Worker 可用时自动在 Worker 内解析;不支持/受限时主线程 MockWorker(沙箱 new Function)复用同一份代码降级,零配置。
  • 构建期内联:解析代码在打包时编译为字符串内联进主包,单入口、无独立 worker 产物。
  • 动态精灵/文本替换、海报、正/逆序、缩放适配、帧区间/播放至指定帧、循环与结束行为。
  • 零 UI 框架依赖,仅构建期依赖 fflate;esm ~40KB / gzip ~13KB(小于官方 svga.lite)。

极致轻量 · 为移动端而生

  • 体积极小、冷启动快:单包 gzip 仅 ~13KB、零运行时依赖,不引入任何 UI 框架与重型运行时,首帧可快速拉起,特别适合移动端低端机与包体敏感场景。
  • 移动端更省电省内存:
    • 复杂动效抽帧渲染(frameThrottling,目标渲染帧率可调):动画时间轴照常推进、动效时长不变,仅降低画面刷新频率,显著降低单帧绘制对主线程的阻塞;
    • Path2D 预缓存 / 帧位图缓存 / 动态文本位图化,把每帧重计算与重复光栅化降到最低,显著降低 GPU/CPU 负载;
    • 视口不可见时自动暂停播放(useIntersectionObserver),滚动列表外动画零开销。
  • 按需装配:解析与渲染均为函数式、可摇树(sideEffects: false),按打包工具自动剔除未用代码,最终体积进一步收缩。

安装

npm i custom-svga
# 或 CDN <script src="https://unpkg.com/custom-svga"></script> → window.CustomSvga

快速开始(Vue3)

<script setup>
import { ref, onBeforeUnmount } from 'vue'
import { Player, Parser } from 'custom-svga'

const canvas = ref(null)
let player = null

async function load() {
  player?.destroy()
  player = new Player(canvas.value, { loop: 0, scaleMode: 'AspectFit' })
  player.onReady(() => player.play())
  const movie = await Parser.loadUrl('https://example.com/anim.svga')
  player.setVideoItem(movie)
}
onBeforeUnmount(() => player?.destroy())
</script>

<template><canvas ref="canvas"></canvas></template>

Player

构造函数

new Player(element, config?)
// element: HTMLCanvasElement | HTMLDivElement(div 容器模式会自动创建并管理画布)

方法

方法 说明
setVideoItem(MovieData | VideoUrlSource) 装载动画数据(Parser 解析结果,或 { url, ...解析选项 } 对象——内部自动 Parser.loadUrl,解析选项平铺:useWorker/cache/useImageBitmap)
play(config?) 开始/恢复播放;传入的 config 会持久更新到实例配置
setConfig(config?) 仅更新实例播放配置(不触发播放),播放中同样即时生效
playRange(start, end, config?) 播放指定帧区间
pause() 暂停,保持当前帧
stop() 停止并应用配置的结束行为(fillMode:末帧/首帧/清空)
skipRender(skip?) 切换/设置是否跳过渲染(帧时间轴仍推进);不传参则切换
stepToFrame(frame, andPlay?) 跳转到指定帧
stepToPercentage(p, andPlay?) 跳转到进度(0~1)
setImage(img | url, key) 动态替换图层图片
setText(text | DynamicText, key) 动态替换图层文本
clearDynamic(key?) 清除动态替换,不传 key 则清空全部
renderPoster(url) 外链图片作静态海报渲染到画布
resize() 按 DOM 容器与 DPR 校准画布尺寸
clear() 清空当前动画数据与画布(保留实例,可再 setVideoItem)
destroy() 彻底销毁实例(画布/监听/内存),需重新 new Player

运行时更新配置

setConfig 只更新配置、不触发播放,适合实例化后动态调整;play(config) 等价于「先 setConfig 再播放」,配置会持久写入实例。

import { SCALE_MODE } from 'custom-svga'

// 静默更新(未播放时可改适配模式、帧缓存、海报等)
player.setConfig({ scaleMode: SCALE_MODE.ASPECT_FILL, maxCacheFrames: 200 })

// 播放中改 fps / 帧区间 / 抽帧同样即时生效
player.setConfig({ fps: 30, frameThrottling: 20 })

// play(config) = setConfig(config) + 播放,且配置持久保留
player.play({ loop: 2 })

事件

事件 回调参数 触发时机
onReady MovieData? 数据就绪
onError Error 运行/加载异常
onStart / onPause / onStop - 对应生命周期
onLoopEnd - 每轮循环结束(含最后一轮)
onEnd - 播放彻底结束(仅当配置有限 loop 达到上限停摆时触发;loop: 0 无限循环与手动 stop/pause 不触发)
onProcess frame: number 每推进一帧
onPoster PosterEventInfo 海报展示/隐藏切换

Parser

静态方法(多个调用共用同一共享 Worker 线程):

Parser.load(source, options?)          // source: url | File | Blob
Parser.loadUrl(url, options?)
Parser.loadFile(file, options?)
Parser.parseBuffer(buffer, options?)
Parser.delete(key)                     // 清除单个缓存
Parser.clear()                         // 清空全部缓存(保留共享 Worker)
Parser.destroy()                       // 清空全部缓存并释放共享 Worker(下次解析按需重建)

实例化(每个实例持有独立 Worker,解析配置在实例化时一次性声明,方法不再逐次传 options):

const parser = new Parser({ useWorker: true, cache: true, autoClose: false })
await parser.loadUrl(url)              // 与静态签名一致,但走独立 Worker 线程
await parser.load(file)                // loadUrl / loadFile / parseBuffer 同理
parser.delete(key) / parser.clear() / parser.destroy()

内存/文件信息(独立导出,内部复用全局缓存):

import { queryMemoryInfo } from 'custom-svga'
await queryMemoryInfo(url, true)       // log=true 打印表格

options / ParserConfig:useWorker(默认 true,false 强制主线程 MockWorker 解析)、useImageBitmap(默认 false,解码为 ImageBitmap)、cache(默认 true,LRU 缓存 20 条)。缓冲解析(loadFile/parseBuffer)需显式传 movieDataId 才会写入缓存(匿名缓冲无稳定键,不缓存以免污染 LRU);实例化时 movieDataId 也是实例级缓存键。实例额外支持 autoClose(默认 false):为 true 时每次解析成功即自动释放当前 Worker(适合低频/一次性解析,用完即释放线程)。

PlayConfig

配置 默认 说明
loop 0 循环次数,0=无限
fps 源文件 覆盖帧率
fillMode forwards 播放结束行为:forwards末帧 / backwards首帧 / clear清空
startFrame / endFrame - 播放区间
direction forward 播放方向:forward / backward(逆序)
scaleMode AspectFit SCALE_MODE:AspectFit / AspectFill / Fill
useIntersectionObserver true 视口不可见优化
invisibleBehavior pause 不可见时 pause(停走)或 skip(仅跳绘制,帧仍走)
frameThrottling 0 抽帧渲染(适合复杂动效):目标渲染帧率上限(fps),时间轴照常推进、时长不变
cacheFrames / maxCacheFrames false / 100 帧缓存(位图化)。仅当循环区间帧数 ≤ maxCacheFrames 时启用,装不下则整体禁用并提示;大画布建议改用 frameThrottling
defaultPoster - 默认静态海报(未播放/出错/clear 时显示)
autoPlay false setVideoItem 装载完成后是否立即自动播放

同构 Worker 说明

  • 解析代码唯一一份(svga.worker),打包时由构建插件编译为 IIFE 字符串内联。
  • useWorker: true 且浏览器支持 → new Worker(new Blob([code])) 真子线程解析。
  • Worker 不可用 / 创建失败 → new MockWorker(code):沙箱 new Function('self', 'globalThis', 'postMessage', 'importScripts', code) 主线程同构解析。
  • 解析带 30s 超时与 onerror 自愈兜底,避免 Promise 悬挂。静态方法共用共享 Worker;new Parser() 每个实例持有独立 Worker,useWorker 模式切换会重建 Worker。
  • ⚠️ MockWorker 依赖 new Function,严格 CSP(无 unsafe-eval)环境下无法降级;真实 Worker 需允许 blob:。

动态替换示例

player.setText({ text: 'Hello', size: '18px', color: '#fff' }, 'avatar') // 替换图层 avatar 为文本
await player.setImage('https://example.com/face.png', 'avatar')          // 或替换为图片
player.clearDynamic('avatar')                                            // 清除单个
player.clearDynamic()                                                    // 清空全部

常见问题

  • 停止后没回到首帧?:stop() 按配置的 fillMode 决定末帧/首帧/清空;如需固定首帧请设 fillMode:'backwards'。
  • 暂停与停止区别:pause() 停在当前帧;stop() 结束并应用 fillMode。
  • 体积:esm/cjs/umd 单文件,fflate 已内联进 worker 字符串,运行时不需额外依赖。

License

MIT © DreamLife(Zhou)

如果觉得好用,欢迎 Star ⭐,也欢迎提交 Issue / PR。

Related Packages

@lottiefiles/dotlottie-vue

Vue wrapper around the dotlottie-web library

1,837,720 929
@fireworks-js/vue

A simple fireworks library!

40,221 1,387
webcut

A powerful video editing canvas UI library for web applications

4,706 252
@dumbshow/vue

The Vue editor for dumbshow: ComposerApp and its panes over @dumbshow/core — mou...

883 0
@byloth/vue-scroll-animator

A simple but fast & powerful library to animate HTML elements while scrolling pa...

750 0

Version History

Version Released License
2.3.1 MIT
2.3.0 MIT
2.2.0 MIT
2.1.0 MIT
2.0.1 MIT