Vue3 实现图片的帧动画方案分享

一、纯 JS (有性能问题会卡顿)

html 复制代码
      <div class="robot-box">
        <img ref="robotImgRef" src="/Greet/Greet_00000.png" alt="" />
      </div>
ts 复制代码
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() 告诉浏览器------你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。

ts 复制代码
onMounted(() => {
  nextTick(() => {
    rAF(animation, 60);
  });
});
ts 复制代码
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

相关推荐
计算机学姐14 分钟前
基于SpringBoot的汉服租赁系统【颜色尺码套装+个性化推荐算法+数据可视化统计】
java·vue.js·spring boot·后端·mysql·信息可视化·推荐算法
+VX:Fegn089515 分钟前
计算机毕业设计|基于springboot + vue建筑材料管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
雪碧聊技术22 分钟前
ElementPlus徽章组件:展示日期面板每天未完成的待办数量
vue.js·日期选择器·elementplus·el-badge徽章组件
沐墨染2 小时前
敏感词智能检索前端组件设计:树形组织过滤与多维数据分析
前端·javascript·vue.js·ui·数据挖掘·数据分析
xkxnq2 小时前
第二阶段:Vue 组件化开发(第 18天)
前端·javascript·vue.js
WebGISer_白茶乌龙桃3 小时前
Cesium实现“悬浮岛”式,三维立体的行政区划
javascript·vue.js·3d·web3·html5·webgl
计算机学姐3 小时前
基于SpringBoot的汽车租赁系统【个性化推荐算法+数据可视化统计】
java·vue.js·spring boot·后端·spring·汽车·推荐算法
不一样的少年_3 小时前
产品催: 1 天优化 Vue 官网 SEO?我用这个插件半天搞定(不重构 Nuxt)
前端·javascript·vue.js
BingoGo3 小时前
免费可商用商业级管理后台 CatchAdmin V5 正式发布 插件化与开发效率的全面提升
vue.js·后端·php
一 乐11 小时前
婚纱摄影网站|基于ssm + vue婚纱摄影网站系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·后端