CSS生成GIF,为什么获取的都是同一帧?

作者站长头像
站长
· 阅读数 10

我使用html2canvas库截取页面元素,为什么生成的图片全是最后一帧的?以下代码可直接复制运行

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  .index {
    width: 300px;
    height: 200px;
    background-color: #eee;
  }

  .box {
    width: 100px;
    height: 50px;
    background-color: #bbb;
  }

  .box2 {
    width: 300px;
    height: 200px;
    background-color: #ccc;
  }

  .animate {
    transform: translateX(200px);
    transition: all 3s ease;
  }
</style>

<body>
  <div class="index">
    <button class="btn">do</button>
    <button class="btn2">transform</button>
    <div class="box"></div>
  </div>
  <div class="box2"></div>

</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gifshot/build/gifshot.min.js"></script>
<script>
  const btn = document.querySelector('.btn')
  const btn2 = document.querySelector('.btn2')
  const ele = document.querySelector('.index')
  const box = document.querySelector('.box')
  const box2 = document.querySelector('.box2')
  let frameArr = []
  btn.addEventListener('click', () => {
    box.classList.add('animate')
    const dur = 3000 // 动画持续时间
    frameArr = [] // 存储每一帧
    const now = Date.now()
    const captureFrame = async () => {
      const canvas = await html2canvas(ele, {
        useCORS: true, // 【重要】开启跨域配置
        scale: window.devicePixelRatio < 3 ? window.devicePixelRatio : 2,
        allowTaint: true, // 允许跨域图片
      })
      const url = canvas.toDataURL("image/png", 1.0)
      console.log('url', url)
      frameArr.push(url)
      if (Date.now() - now < dur) {
        requestAnimationFrame(captureFrame)
      } else {
        console.log('frameArr---22', frameArr)
        // 获取完所有截图后,可以进行下一步操作
      }
    }
    captureFrame()
  })

  btn2.addEventListener('click', () => {
    console.log('btn2 click', frameArr)
    gifshot.createGIF({
      images: frameArr,
      gifWidth: 300,
      gifHeight: 200,
      interval: 0.15,
      numWorkers: 2,
      progressCallback: function (progress) {
        // 显示 GIF 转换进度
        console.log('GIF 转换进度:' + progress * 100 + '%');
      },
      completeCallback: function (gifUrl) {
        // 在页面上显示 GIF 图像
        console.log('GIF 转换完成:' + gifUrl);
      }
    }, (obj) => {
      console.log('obj', obj);
      if (!obj.error) {
        const animatedImage = document.createElement('img');
        animatedImage.src = obj.image
        box2.appendChild(animatedImage);
      }
    });
  })
</script>

</html>
回复
1个回答
avatar
test
2024-07-01

因为 html2canvas,顾名思义,它是自己画的界面,不是直接从浏览器获取的画面截图,那么自然每次 GIF 都是第一帧。

要解决的话,可能必须在截图的时候手动替换成按时间换算出来的那一帧截图。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容