使用 `jsgif` 在动画 GIF 上构建图层

Using `jsgif` to build layers over animated GIFs

我希望得到一些关于使用优秀 libgif.js library 的帮助或指导。

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

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

但是,文本图像没有显示在最终 canvas 中,我有点不知道如何解决这个问题。

为什么 textImage 的大小合适并且(有点)显然放在 canvas 上但没有显示在最终结果中,这对任何人来说都是显而易见的吗?

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

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

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]);
  }
}

注:此方案最初是根据this question from this JSFiddle评论中Arend的方案。

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

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

与其在文档中附加库返回的 canvas,您可以将其保留在屏幕外,然后将其绘制在另一个可见的 canvas.
上 在这个新 canvas 上,您还将在 rAF 循环中绘制文本图像。

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>