In a recent request, the designer gave me two animated images in apng format. The requirements are to be in the same position. The first animated image is played once, and the second animated image is played in a loop, with a natural connection and transition in the middle.
The GIF in apng format is the first time I have used it, and my understanding of it is limited to "moving png pictures". After several searches, I finally completed some knowledge points of apng. Since there is a lot of information about apng on the Internet, I won't introduce apng too much here.
The browser does not provide api by default for us to manipulate apng, so we can't directly listen to apng's playback events, let alone control its playback actions. How to do it? Fortunately, there is a versatile npm. When searching for apng directly apng-js , which can meet our needs.
apng-js is written very concisely, and its core principle is to parse the data of apng images according to the apng specification, and then draw them onto the canvas. At the same time, it also provides an api that allows us to control the playback, pause, and reset of apng pictures, and can monitor events generated during the playback of these pictures, so that we have full control over apng. Not much nonsense, let us see how apng-js fulfills our needs directly on the example.
<canvas>
element in the html, and then introduce the apng-js library to initialize the canvas size and image resources.
<canvas id="canvas"></canvas>
// js file
import parseAPNG from "https://cdn.skypack.dev/apng-js@1.1.1";
const img1Src = 'https://official-account-web-1251316161.cos.ap-guangzhou.myqcloud.com/mqq-static/open-platform-animate-1-new.png'
const img2Src = 'https://official-account-web-1251316161.cos.ap-guangzhou.myqcloud.com/mqq-static/open-platform-animate-2-new.png'
const canvas = document.querySelector('#canvas')
canvas.width = 640;
canvas.height = 540;
canvas.style = 'zoom: 0.75';
const ctx = canvas.getContext('2d');
- Since apng-js only accepts
ArrayBuffer
form of 060eab32549e4a, we need to write our own function to convert apng into ArrayBuffer.
// js file
// 获取图片并转化成 ArrayBuffer
function getImgBuffer(url) {
return new Promise(async resolve => {
const blob = await fetch(url).then(res => res.blob());
const reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = () => {
resolve(reader.result);
};
});
}
- After getting the apng image resource in ArrayBuffer format, it can be parsed and used by apng-js. Here I created a
createApngPlayer()
, which outputs the player instance of apng-js, which is convenient for our subsequent use.
async function createApngPlayer(url, ctx, options = {}) {
const imgBuffer = await getImgBuffer(url);
const apng = parseAPNG(imgBuffer);
Object.keys(options).forEach(key => {
apng[key] = options[key];
});
const player = await apng.getPlayer(ctx);
return player;
}
- After you get the player instance, you can use it to control the playback of apng!
;(async () => {
const player1 = await createApngPlayer(img1Src, ctx, { numPlays: 1 }); // 设置图1的 numPlays 为1,让其只播放一次
const player2 = await createApngPlayer(img2Src, ctx);
player1.play(); // 图1播放
player1.on('end', () => { // 监听图1的播放,当其播放完毕时,马上开始图2的播放
player2.play();
});
})()
The effect can be seen in my example in Codepen:
https://codepen.io/jrainlau/pen/abWmaNK
That's it!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。