【问题标题】:how to convert frames of GIF into spritesheet如何将 GIF 帧转换为 spritesheet
【发布时间】:2021-10-07 12:46:01
【问题描述】:

我正在尝试合并 GIF 中的多个帧以将它们转换为 spritesheet。我能够以某种方式使用 libgif.js 提取帧 这是我的代码。我要放置所有图像的画布是空的,最后我不知道它有什么问题。

<img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
    rel:rubbable="0" />

  <div id="frames">
  </div>
  <canvas id="myCanvas" style="border:1px solid #d3d3d3;">
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>
<script>
  $(document).ready(function () {
    $('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 (var i = 0; i < rub.get_length(); i++) {
            total += 1;
            rub.move_to(i);
            var canvas = cloneCanvas(rub.get_canvas());

            $("#frames").append('<img id = "' + i + '"src= "' + canvas + '">');

          }
          for (var i = 0; i <= total; i++) {
            id = i.toString();
            var img = document.getElementById(id);
            window.onload = function () {

              var c = document.getElementById("myCanvas");
              var ctx = c.getContext("2d");

              ctx.drawImage(img, 10, 10);
            }
          }
        });
      }
    });
  });

  function cloneCanvas(oldCanvas) {
    var img = oldCanvas.toDataURL("image/png");
    return img;
  }
</script>

【问题讨论】:

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


    【解决方案1】:

    您的解决方案中的主要问题是您正在循环所有插入的帧图像并使用window.onload 并期望在画布上绘制图像。但是,您要在图像元素上分配windows.onload之后图像已经在之前的(for i = 0) 迭代中通过$("#frames").append(... 附加到dom。这意味着您的 onload 处理程序将在事件触发后注册。

    我将您的代码重新排列到下面的 sn-p 中,以确保在将图像帧附加到文档之前已注册 onload

    在此解决方案中,我通过将图像帧一个接一个地垂直放置来创建“spritesheet”。相应地调整解决方案以创建所需的“spritesheet 布局”。

    棘手的部分是您需要以动态方式为画布设置widthheight,这意味着您必须等待所有图像帧都成为loaded 进入文档并测量它们集体宽度和高度。 算法应该是:

    1. 收集图像帧的所有宽度和高度onload
    2. 计算canvas.widthcanvas.height 的总数取决于 您想要的布局(在我的垂直解决方案中 这意味着使用最大图像宽度作为画布宽度和 所有图像高度的总和为高度。如果您需要不同的 spritesheet 布局,那么您需要以不同方式调整此逻辑)
    3. 在画布上绘制所有图像,此时已经足够了 适合所有 gif 帧图像的宽度和高度。

    在我的解决方案中,我没有实现此算法,而是在为您的特定 gif 示例手动计算 max-img-width 和 total-img-height 之后硬编码画布宽度和高度。

    $(document).ready(function () {
        const c = document.getElementById("myCanvas");
        const ctx = c.getContext("2d");
        let canvasWidth = 0;
        let canvasHeight = 0;
        $('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());
    
                const img = $('<img id = "' + i + '"src= "' + canvas + '">');
                img.on('load', function() {
                  // draw the image
                  ctx.drawImage(this, 0, canvasHeight);
                  // extend canvas width, if newly loaded image exceeds current width
                  canvasWidth = $(this).width() > canvasWidth ? $(this).width() : canvasWidth;
                  // add canvas height by the newly loade image height value
                  canvasHeight += $(this).height();
                  // resize sprite-canvas to host the new image
                  canvas.width = canvasWidth;
                  canvas.height = canvasHeight;
                });
                $("#frames").append(img);
              }
            });
          }
        });
      });
    
      function cloneCanvas(oldCanvas) {
        var img = oldCanvas.toDataURL("image/png");
        return img;
      }
    Gif:
    <img hidden src="https://upload.wikimedia.org/wikipedia/commons/2/2c/Rotating_earth_%28large%29.gif" rel:auto_play="0"
        rel:rubbable="0" />
    <hr />
    Frames:
    <div id="frames">
    </div>
    <hr />
    Canvas:
    <hr />
    <canvas id="myCanvas" style="border:1px solid #d3d3d3;" width="400" height="17600">
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://unpkg.com/jsgif@1.0.2/libgif.js"></script>

    【讨论】:

    • omg 非常感谢你不知道因为我被困在这个问题上多久了非常感谢你
    • 我很高兴它被证明是有用的
    猜你喜欢
    • 2022-01-23
    • 2021-02-01
    • 2012-05-03
    • 2011-06-21
    • 2014-09-02
    • 1970-01-01
    • 2021-09-19
    • 2017-07-20
    • 2012-06-17
    相关资源
    最近更新 更多