You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
3.3 KiB
HTML
116 lines
3.3 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Document</title>
|
|
</head>
|
|
|
|
<body>
|
|
<div>
|
|
<canvas id="gifCanvas"></canvas>
|
|
<div>
|
|
<button onclick="window.gifPlayer.start()">start</button>
|
|
<button onclick="window.gifPlayer.stop()">stop</button>
|
|
|
|
<input type="number" max="10" min="0" step="0.1" value="1"><button onclick="window.gifPlayer.radioRate=Number(this.previousElementSibling.value)">播放速率比</button>
|
|
</div>
|
|
|
|
</div>
|
|
<script>
|
|
const gifCanvas = document.querySelector('#gifCanvas');
|
|
|
|
|
|
class GifPlayer {
|
|
|
|
/**
|
|
*
|
|
* @param {*} template 图片模板路径:变量,{i}
|
|
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
|
|
* @param {*} canvas 画布
|
|
* @param {*} radioRate 播放速率比,0=不播放 默认1
|
|
*/
|
|
constructor(template, num, canvas, radioRate) {
|
|
this.load = false;
|
|
this.canvas = canvas;
|
|
this.radioRate = radioRate;
|
|
this.ctx = this.canvas.getContext('2d');
|
|
// this.ctx.save();
|
|
this.#init(template, num);
|
|
}
|
|
|
|
async #init(template, num) {
|
|
this.imgs = await this.loadImgs(template, num);
|
|
this.canvas.dispatchEvent(new CustomEvent('loadend',{bubbles:false}))
|
|
this.load = true;
|
|
this.canvas.width = this.imgs[0].naturalWidth * window.devicePixelRatio;
|
|
this.canvas.height = this.imgs[0].naturalHeight * window.devicePixelRatio;
|
|
this.i = 0;
|
|
this.time = Date.now();
|
|
this.playing = true;
|
|
this.ctx.drawImage(this.imgs[0], 0, 0, this.canvas.width, this.canvas.height);
|
|
this.#backgroudPlay();
|
|
}
|
|
|
|
/**
|
|
* 加载图片
|
|
* @param {*} template 图片模板路径:变量,{i}
|
|
* @param {*} num 图片的总数{i}=0~(num-1), 默认34
|
|
*/
|
|
loadImgs(template, num = 34) {
|
|
return new Promise((resolve, reject) => {
|
|
const imgs = [];
|
|
const ps = [];
|
|
for (let i = 0; i < num; i++) {
|
|
const img = new Image();
|
|
img.src = template.replace('{i}', i);
|
|
imgs[i] = img;
|
|
ps.push(new Promise((resolve1, reject1) => {
|
|
img.onload = resolve1;
|
|
img.onerror = reject1;
|
|
}));
|
|
}
|
|
Promise.all(ps).then(() => {
|
|
resolve(imgs);
|
|
}).catch(err => {
|
|
reject(err);
|
|
})
|
|
})
|
|
}
|
|
|
|
#backgroudPlay() {
|
|
if (this.radioRate === 0 || !this.playing) {
|
|
requestAnimationFrame(()=>{this.#backgroudPlay()});
|
|
return;
|
|
}
|
|
|
|
let now = Date.now();
|
|
if (now - this.time >= 50 / this.radioRate) {
|
|
this.time = now;
|
|
this.i++;
|
|
if (this.i >= this.imgs.length) {
|
|
this.i = 0;
|
|
}
|
|
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
|
// this.ctx.restore();
|
|
this.ctx.drawImage(this.imgs[this.i], 0, 0, this.canvas.width, this.canvas.height);
|
|
}
|
|
requestAnimationFrame(()=>{this.#backgroudPlay()});
|
|
}
|
|
|
|
start() {
|
|
this.playing = true;
|
|
}
|
|
|
|
stop() {
|
|
this.playing = false;
|
|
}
|
|
|
|
}
|
|
window.gifPlayer = new GifPlayer('./gif/{i}.png', 34, gifCanvas, 1);
|
|
|
|
</script>
|
|
</body>
|
|
|
|
</html> |