一、纯 JS (有性能问题会卡顿)
<div class="robot-box">
<img ref="robotImgRef" src="/Greet/Greet_00000.png" alt="" />
</div>
const delay = 30;
const imgCount = 109;
let i = 0;
const robotImgRef = ref<HTMLImageElement | null>(null);
const animation = (i) => {
if (i === imgCount) {
i = 0;
animation(i);
return;
}
let path;
if (Number(i) < 10) {
path = '0000' + i;
} else if (Number(i) < 100) {
path = '000' + i;
} else if (Number(i) < 1000) {
path = '00' + i;
}
robotImgRef.value.src = `/Greet/Greet_${path}.png`;
robotImgRef.value.onload = () => {
setTimeout(() => {
animation(i + 1);
}, delay);
};
};
onMounted(() => {
nextTick(() => {
animation(0);
});
});
二、window.requestAnimationFrame()
window.requestAnimationFrame——MDN
window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。
onMounted(() => {
nextTick(() => {
rAF(animation, 60);
});
});
const imgCount = 109;
let i = 0;
const robotImgRef = ref<HTMLImageElement | null>(null);
const animation = () => {
if (i === imgCount) {
// 重新开始
i = 0;
return;
}
let path;
if (Number(i) < 10) {
path = '0000' + i;
} else if (Number(i) < 100) {
path = '000' + i;
} else if (Number(i) < 1000) {
path = '00' + i;
}
if (robotImgRef.value) {
robotImgRef.value.src = `/Greet/Greet_${path}.png`;
}
i++;
};
/**
* @param {number} [fps] - 帧率
* @param {function} callback - 动画逻辑
* @return {function} cancelRFA - 取消播放
*/
function rAF(callback, fps = 24) {
let last = Date.now();
let delta = last;
const interval = 1000 / fps;
let cancel = false;
function draw() {
if (cancel) return;
requestAnimationFrame(draw);
let now = Date.now();
delta = now - last;
if (delta > interval) {
/* 这里不能简单last = now,否则出现细微时间差问题。例如fps= 10,每帧100ms,
而现在每16ms(60fps)执行一次draw。16*7=112>100,需要7次才实际绘制一帧。这个情况下,
实际10帧需要 112*10=1120ms>1000ms 才绘制完成。
当 now - (delta % interval) 时,会将时间修正 delta % interval = 12ms,
实际10帧需要 112+(112-12)*9=1012ms 绘制完成。
*/
last = now - (delta % interval);
callback();
}
}
draw();
return function cancelRAF() {
cancel = true;
};
}
三、CSS 实现
请看这篇博客:实现序列帧图片动画的3种方式
四、叫 UI 换 GIF 图片
我最后采用的是叫 UI 换 GIF 了😁
只有麻烦下 UI 了哈哈哈哈
感谢
实现序列帧图片动画的3种方式
利用 requestAnimationFrame API 流畅播放序列帧动画并控制帧率FPS