【问题标题】:如何使用 Javascript 将 Gif 转换为 spritesheet
【发布时间】:2022-01-23 16:37:59
【问题描述】:

我正在使用 Libgif 从 gif 获取帧。 然后我在 div 中使用 Id = frames 附加这些帧。 然后我正在拍摄这些帧并尝试在画布中一个接一个地添加每个帧以制作精灵表。

最后,我在画布中获得了一个图像,但我没有获得不同的帧,而是在精灵表中获得了相同的图像。 请帮我找出问题。

假设 gif 的帧数不会超过 100,我将画布宽度设为 10000。

c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.beginPath();
var imageGiF = "";
var total = 0;
let canvasWidth = 0;
let canvasHeight = 0;
$('div.gifimage img').each(function(idx, img_tag) {
  var total = 0;
  if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
    var rub = new SuperGif({
      gif: img_tag,
      progressbar_height: 0
    });
    rub.load(function() {
      for (let i = 0; i < rub.get_length(); i++) {
        total += 1;
        rub.move_to(i);
        // var canvas = cloneCanvas(rub.get_canvas());
        var canvas = rub.get_canvas().toDataURL("image/png");
        img = $('<img id = "gifframe' + i + '"src= "' + canvas + '" class= frameimages>');

        $("#frames").append(img);

      }
      var frameimages = document.getElementById("frames").querySelectorAll(".frameimages");
      var totalimages = frameimages.length;

      x = 0;
      y = 0;
      for (let i = 0; i < frameimages.length; i++) {
        img = document.getElementById("gifframe" + i + "");
        img.onload = function() {
          ctx.drawImage(img, i * 100, 0, 100, 100);
          total++;
          console.log(total);
        }
      }
      totalwidth = (total) * 100;
      c.width = totalwidth;
      c.height = 100;
      setTimeout(() => {
        imageGiF = c.toDataURL("image/png");
        console.log(imageGiF);
        // addBgimg(imageGiF)
      }, 10);
    });
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/buzzfeed/libgif-js/master/libgif.js"></script>
<div class="gifimage" id="placehere">
  <img src="https://media1.giphy.com/media/bzUwzbxcvJ3XQlcnoi/giphy.gif" alt="">

</div>
<div id="frames" class="classGIF"></div>
<canvas id='myCanvas' width="10000" height="300"></canvas>

【问题讨论】:

  • 我让你成为了你应该让自己成为的 sn-p
  • 究竟是什么不起作用?我看到了动画,也看到了各个帧。
  • @Tschallacka 添加到画布中的图像是相同的。它应该是不同的,因为它是一个精灵表。这是gif的最后一帧。我不知道为什么会这样。我们从画布中获得了一个图像源或 dataUrl。仔细检查该图像,您会发现问题所在
  • 啊,现在我明白了,底部的图像被控制台输入隐藏了。
  • @Tschallacka 是的,我确信这是我正在做的一些小错误。可能是我使用了错误的逻辑

标签: javascript html5-canvas fabricjs gif sprite-sheet


【解决方案1】:

您在事件处理程序中使用img 循环浏览图像。 但是,外部作用域中的这个变量 img 被每个循环覆盖,直到它完成循环所有内容,然后 img 卡在添加的最后一帧。
然后,当事件处理程序触发时,它会在每个实例中添加最后一帧,因为那是当时img 的值。循环在图像加载之前完成。

通过将它添加到它自己的 scope 并通过将其包装在一个函数中,变量被保留。

我还修改了您的代码以将 DOM img 元素存储在一个数组中,因此您不需要昂贵的 DOM 查找,这会使您的代码更快一点。

我在代码中添加了 cmets 来解释我的更改。

c = document.getElementById("myCanvas");
ctx = c.getContext("2d");
ctx.clearRect(0, 0, ctx.width, ctx.height);
ctx.beginPath();
var imageGiF = "";
var total = 0;
let canvasWidth = 0;
let canvasHeight = 0;
$('div.gifimage img').each(function(idx, img_tag) {
  var total = 0;
  if (/^.+\.gif$/.test($(img_tag).prop("src"))) {
    var rub = new SuperGif({
      gif: img_tag,
      progressbar_height: 0
    });
    rub.load(function() {
      // An array for the image references
      let images = [];
      // Keep the reference to save on expensive DOM lookups every iteration.
      let frames = $("#frames");
      for (let i = 0; i < rub.get_length(); i++) {
        total += 1;
        rub.move_to(i);
        // var canvas = cloneCanvas(rub.get_canvas());
        var canvas = rub.get_canvas().toDataURL("image/png");
        img = $('<img id = "gifframe' + i + '"src= "' + canvas + '" class="frameimages">');
        
        // Use the reference to append the image.
        frames.append(img);
        
        // Add image to images array with the current index as the array index.
        // Use the jQuery get method to get the actual DOM element.
        images[i] = img.get(0);
      }
      var frameimages = document.getElementById("frames").querySelectorAll(".frameimages");
      var totalimages = frameimages.length;

      x = 0;
      y = 0;
      
      // Loop through all the images in the image array
      // Using a scope so the reference to img won't be overridden.
      images.forEach((img, index) => {
        img.onload = () => {
          ctx.drawImage(img, index * 100, 0, 100, 100);
          total++;
          console.log(total);
        } 
      })
      
      
      totalwidth = (total) * 100;
      c.width = totalwidth;
      c.height = 100;
      setTimeout(() => {
        imageGiF = c.toDataURL("image/png");
        console.log(imageGiF);
        // addBgimg(imageGiF)
      }, 10);
    });
  }
});
#frames { display:none;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/buzzfeed/libgif-js/master/libgif.js"></script>
<div class="gifimage" id="placehere">
  <img src="https://media1.giphy.com/media/bzUwzbxcvJ3XQlcnoi/giphy.gif" alt="">

</div>
<div id="frames" class="classGIF"></div>
<canvas id='myCanvas' width="10000" height="300"></canvas>

【讨论】:

  • 非常感谢!终于成功了
猜你喜欢
  • 2021-10-07
  • 2020-06-27
  • 2014-09-02
  • 1970-01-01
  • 1970-01-01
  • 2021-09-19
  • 2017-07-20
  • 2019-01-31
  • 2013-06-05
相关资源
最近更新 更多