最近需求中,设计师给了我两个apng格式的动画,要求是在同一个位置,第一个动画播放一次,第二个动画循环播放,中间有自然的连接和过渡。apng格式的动画我是第一次用,对它的理解也仅限于“会动的png图片”。经过几番查找,终于完成了apng的一些知识点。由于网上关于apng的资料很多,这里就不过多介绍apng了。默认情况下,浏览器没有提供api给我们操作apng,所以我们不能直接监听apng的播放事件,更不能控制它的播放动作。怎么做?幸运的是,有全能的npm。直接搜索apng,会出现一个名为apng-js的库,可以满足我们的需求。apng-js写的很简洁,其核心原理就是按照apng的规范解析apng图片的数据,然后绘制到canvas上。同时,它也提供了API让我们可以控制apng图片的播放、暂停、重置,以及监听这些图片在播放过程中产生的事件,让我们对apng拥有完全的控制权。废话不多说,直接上例子,让我们看看apng-js是如何完成我们的需求的。首先准备好html中的//js文件从“https://cdn.skypack.dev/apng-js@1.1.1”导入parseAPNG;constimg1Src='https://official-account-web-1251316161.cos.ap-guangzhou.myqcloud.com/mqq-static/open-platform-animate-1-new.png'constimg2Src='https://official-account-web-1251316161.cos.ap-guangzhou.myqcloud.com/mqq-static/open-platform-animate-2-new.png'constcanvas=document.querySelector('#canvas')canvas.width=640;canvas.height=540;canvas.style='zoom:0.75';constctx=canvas.getContext('2d');由于apng-js只接受ArrayBuffer形式的数据,所以我们需要自己写一个函数将apng转为ArrayBuffer。//js文件//获取图像并将其转换为ArrayBufferfunctiongetImgBuffer(url){returnnewPromise(asyncresolve=>{constblob=awaitfetch(url).then(res=>res.blob());constreader=newFileReader();reader.readAsArrayBuffer(blob);reader.onload=()=>{resolve(reader.result);};});}得到ArrayBuffer格式的apng图片资源后,就可以使用apng了-js来解析和使用。这里我创建了一个名为createApngPlayer()的公共函数来输出apng-js播放器实例供我们后续使用。异步函数createApngPlayer(url,ctx,options={}){constimgBuffer=awaitgetImgBuffer(url);constapng=parseAPNG(imgBuffer);Object.keys(options).forEach(key=>{apng[key]=options[key];});constplayer=awaitapng.getPlayer(ctx);returnplayer;}拿到player实例后,就可以用它来控制apng的播放了!;(async()=>{constplayer1=awaitcreateApngPlayer(img1Src,ctx,{numPlays:1});//设置图1的numPlays为1,这样只播放一次constplayer2=awaitcreateApngPlayer(img2Src,ctx);player1.play();//图1播放player1.on('end',()=>{//监听图1的播放,播放完毕立即开始播放图2player2.play();});})()实现效果,可以看我在Codepen中的例子:https://codepen.io/jrainlau/p...大功告成!
