如何使用JavaScript获取gif图像的持续时间

4

我试图只显示一次GIF图片,所以我使用了以下代码来实现。

    var ui_img = document.getElementById("ui_image");
    ui_img.hidden = false;
    setTimeout(function () {
        ui_img.hidden = true;
    }, 8000);

但我知道所有的gif并不具有相同的持续时间。 我该如何解决这个问题?

3个回答

5
你可以尝试使用这个库gifuct-js
主要使用parseGIF()函数,然后使用decompressFrames()函数获取一个frame数组,每个frame有一个delay属性,表示该frame显示的时间。所以,你可以将所有frame的delay相加,得到GIF图像的总持续时间。
使用示例-来自其Github页面的修改代码示例:
import { parseGIF, decompressFrames } from 'gifuct-js'

var oReq = new XMLHttpRequest();
oReq.open("GET", gifURL, true);
oReq.responseType = "arraybuffer";

oReq.onload = function (oEvent) {
    var arrayBuffer = oReq.response; // Note: not oReq.responseText
    if (arrayBuffer) {
        var gif = parseGIF(arrayBuffer);
        var frames = decompressFrames(gif, true);
        // do something with the frame data

        // get total time in ms
        var totalTime = frames
            .map(frame => frame.delay)
            .reduce((a, b) => a + b);
    }
};

oReq.send(null);

3

这将返回持续时间值

isGifAnimated(file) {
    return new Promise((resolve, reject) => {
      try {
        let fileReader = new FileReader();
        fileReader.readAsArrayBuffer(file);
        fileReader.onload = (event) => {
          let arr = new Uint8Array(fileReader.result);
          let duration = 0;
          for (var i = 0; i < arr.length; i++) {
            if (arr[i] == 0x21
              && arr[i + 1] == 0xF9
              && arr[i + 2] == 0x04
              && arr[i + 7] == 0x00) {
              const delay = (arr[i + 5] << 8) | (arr[i + 4] & 0xFF)
              duration += delay < 2 ? 10 : delay;
            }
          }
          resolve(duration / 100);
        }

      } catch (e) {
        reject(e);
      }
    });
  }

3
如果我能改进@Alex的代码,我会使其变成同步的,更加通用,可以处理大多数来源而不仅仅是文件(还可以避免长时间的不必要的Promise链)。我只会接受一个Uint8array,它可以有一个字节偏移量并且是一个较大的zip文件的一部分或其他类似的东西。这样它就可以与NodeJS文件系统和fetch一起工作了。同时,我也会使用blob.arrayBuffer(),而不是使用过时的FileReader。

fetch('https://media0.giphy.com/media/FIHThOlkZK3r8HTj9t/giphy.gif')
  .then(res => res.arrayBuffer())
  .then(ab => isGifAnimated(new Uint8Array(ab)))
  .then(console.log)

/** @param {Uint8Array} uint8 */
function isGifAnimated (uint8) {
  let duration = 0
  for (let i = 0, len = uint8.length; i < len; i++) {
    if (uint8[i] == 0x21
      && uint8[i + 1] == 0xF9
      && uint8[i + 2] == 0x04
      && uint8[i + 7] == 0x00) 
    {
      const delay = (uint8[i + 5] << 8) | (uint8[i + 4] & 0xFF)
      duration += delay < 2 ? 10 : delay
    }
  }
  return duration / 100
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接