APNG第二次页面刷新后不同步,如何监听其动画播放完成事件?
APNG动画时序异常问题修复方案
问题原因
你之前用setTimeout实现时序控制的方式存在天然缺陷:固定延时没有匹配APNG实际的加载、解码、播放时长,页面刷新后缓存状态变化会导致资源加载耗时大幅波动,进而出现动画丢帧、抖动、时序错乱的问题。
APNG播放完成事件监听方案
原生<img>标签没有提供专门的APNG播放完成事件,有两种成熟方案可以精准捕获播放结束时刻:
- 方案1:用
apng-js解析APNG的帧元数据,计算出动画总时长,结合资源加载完成事件触发计时,精度远高于固定延时 - 方案2:用Canvas手动接管APNG帧渲染逻辑,完全自主控制播放进度,可实现零误差的播放结束回调
具体修复步骤
1. 预加载所有资源
先确保所有动画、静态资源加载完成后再启动播放逻辑,避免资源加载延迟导致的时序错乱:
const preloadImage = (src) => { return new Promise((resolve, reject) => { const img = new Image() img.src = src img.crossOrigin = 'anonymous' img.onload = () => resolve(img) img.onerror = reject }) } // 并行预加载所有资源 const [entryApng, loopApng, staticPng] = await Promise.all([ preloadImage('入场动画地址.apng'), preloadImage('循环动画地址.apng'), preloadImage('静态图地址.png') ])
2. 解析入场APNG实际时长
用apng-js解析入场APNG的总播放时长,替换原有的固定setTimeout时长:
import parseAPNG from 'apng-js' // 获取入场APNG的二进制数据并解析 const entryBuffer = await fetch(entryApng.src).then(res => res.arrayBuffer()) const apngData = parseAPNG(entryBuffer) // 累加所有帧的延时得到总播放时长 const entryTotalDuration = apngData.frames.reduce((total, frame) => total + frame.delay, 0)
3. 实现精准时序控制
const animContainer = document.querySelector('#动画容器元素') // 先播放入场动画 animContainer.appendChild(entryApng) // 入场动画播放完成后自动切循环动画 const entryTimer = setTimeout(() => { animContainer.removeChild(entryApng) animContainer.appendChild(loopApng) }, entryTotalDuration) // 触摸事件触发后切静态图 animContainer.addEventListener('touchstart', () => { clearTimeout(entryTimer) animContainer.innerHTML = '' animContainer.appendChild(staticPng) }, { once: true })
进阶零误差方案(可选)
如果对时序精度要求极高,可以直接用apng-js提供的播放器能力,通过Canvas渲染,直接监听播放结束事件:
const canvas = document.createElement('canvas') canvas.width = apngData.width canvas.height = apngData.height animContainer.appendChild(canvas) const player = apngData.getPlayer(canvas.getContext('2d')) // 播放入场动画 player.play() // 监听入场动画播放完成事件,直接切循环动画 player.onended = () => { player.stop() // 插入循环APNG或用同样方式播放循环动画 animContainer.removeChild(canvas) animContainer.appendChild(loopApng) }
内容的提问来源于stack exchange,提问作者Rihards Okmanis
相关产品推荐
相关产品推荐

