【问题标题】:Using `jsgif` to build layers over animated GIFs使用 `jsgif` 在动画 GIF 上构建图层
【发布时间】:2018-01-16 17:35:37
【问题描述】:

我希望获得有关使用优秀libgif.js library 的帮助或指导。

我的目标是获取一个具有动画 gif 和具有透明背景的文本 png 的页面,然后显示重叠的 2 个图像,以便可以将生成的图像复制到剪贴板。

我已经熟悉了libgif.js 库并拥有succeeded in using it to build a canvas from an animated gif and have it remain animated

但是,文本图像没有显示在最终画布中,我对如何解决这个问题有点迷茫。

为什么textImage 的大小正确并且(在某种程度上)明显地放置在画布上,但没有显示在最终结果中,任何人都清楚吗?

作为一个附带问题,有谁知道为什么进度条一开始很快完成,然后第二次进展得更慢?

HTML 比较长,但JSFiddle 的 JS 如下所示(对于那些不愿意点击链接的人)。

function doit() {
  var isGIF = true; // always true for now TODO: better way to test if-gif than regex for ".gif"
  var previewContainer = document.getElementById("previewContainer");
  var textImage = document.getElementById("textImage");
  var templateImage = document.getElementById("templateImage");
  var w = document.getElementById("templateImage").width;
  var h = document.getElementById("templateImage").height;

  previewContainer.removeChild(previewContainer.children[1]);

  if (isGIF) {
    var gif = new SuperGif({
      gif: templateImage,
      progressbar_height: 5,
      auto_play: true,
      loop_mode: true,
      draw_while_loading: true
    });

    gif.load();
    var canvas = gif.get_canvas();
    var context = canvas.getContext('2d');
    context.drawImage(textImage, 0, 0, w, h);

    previewContainer.replaceChild(canvas, previewContainer.children[0]);
  }
}

注意:这个解决方案最初是基于Arendthis question的cmets中来自this JSFiddle的解决方案。

【问题讨论】:

    标签: javascript canvas gif


    【解决方案1】:

    您必须调整库才能访问其渲染循环(如 frame_rendered 事件)。
    这样,您就可以在库在每一帧绘制的图像上添加您想要的任何内容。

    但由于我懒得在那里挖掘,这里有一个解决方法:

    除了将库返回的画布附加到文档中之外,您还可以将其保留在屏幕外,并将其绘制在另一个可见的画布上。
    在这个新的画布上,您还将在 rAF 循环中绘制 textImage。

    function doit() {
      var previewContainer = document.getElementById("previewContainer");
      var textImage = document.getElementById("textImage");
      var templateImage = document.getElementById("templateImage");
      var w = templateImage.width;
      var h = templateImage.height;
      previewContainer.removeChild(previewContainer.children[1]);
    
      var gif = new SuperGif({
        gif: templateImage,
        progressbar_height: 5,
        auto_play: true,
        loop_mode: true,
        draw_while_loading: true
      });
    
      gif.load();
    
      var gif_canvas = gif.get_canvas(); // the lib canvas
      // a copy of this canvas which will be appended to the doc
      var canvas = gif_canvas.cloneNode();
      var context = canvas.getContext('2d');
    
      function anim(t) { // our animation loop
        context.clearRect(0,0,canvas.width,canvas.height); // in case of transparency ?
        context.drawImage(gif_canvas, 0, 0); // draw the gif frame
        context.drawImage(textImage, 0, 0, w, h); // then the text
        requestAnimationFrame(anim);
      };
      anim();
    
      previewContainer.replaceChild(canvas, previewContainer.children[0]);
    }
    <script src="https://cdn.rawgit.com/buzzfeed/libgif-js/master/libgif.js"></script>
    <div>
      <input type="submit" id="doit" value="Do it!" onclick="doit()" />
    </div>
    <div id="previewContainer">
      <img id="templateImage" src="https://i.imgur.com/chWt4Yg.gif" />
      <img id="textImage" src="https://i.stack.imgur.com/CmErq.png" />
    </div>

    【讨论】:

    • 这是一个很好的开始,@Kaiido,谢谢!我能看到的唯一问题是,当我复制生成的图像时,它不是动画的(将动画 gif 部分冻结到一个框架中)。关于如何解决这个问题的任何想法? (我还不确定为什么会这样,只是测试了解决方案,但还没有真正理解它)。
    • @pdro 我不确定我明白你在说什么......当你复制什么时?画布?就像“右键单击 => 将图像另存为..”?如果是这样,那么它与 libgif.js 中的相同,它不再是 gif,它是一个静态画布,它在 js 动画循环中更新。您想将结果导出为动画 gif 吗?那么它不是libgif可以做的一部分。 gif.js 可以做到,但我认为你必须采取完全不同的方法(就像这里一样,一次控制所有提取的帧 1 非常重要)
    • 谢谢,@Kaiido - 没错,我正在尝试获取它,以便我可以复制生成的动画 gif 并将其粘贴到电子邮件正文中并让它继续动画。你所说的控制提取的帧是有道理的,当我有机会时,我会试一试。如果你有任何你研究过的例子,我不会拒绝:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 2014-07-21
    • 2013-12-29
    • 1970-01-01
    • 2013-08-28
    相关资源
    最近更新 更多