HTML5画布中的动态GIF

55
在HTML5中,我如何轻松地绘制一个动态GIF到画布上(请不要使用太复杂的代码),在画布上只有第一帧被显示(使用drawImage)?

3
这可能会有用:https://github.com/matt-way/gifuct-js。 - user993683
另一个值得一看的库:https://github.com/benwiley4000/gif-frames - user993683
6个回答

17

我相信您正在寻找http://slbkbs.org/jsgif

不幸的是,DOM不会公开GIF的单个帧,因此需要通过下载GIF(使用XMLHttpRequest),解析它,并在<canvas>上绘制来完成。


16

如果没有可用的自动化GIF文件画布动画,您可以尝试使用雪碧图,但这确实需要更多的代码。

var img_obj = {
    'source': null,
    'current': 0,
    'total_frames': 16,
    'width': 16,
    'height': 16
};

var img = new Image();
img.onload = function () { // Triggered when image has finished loading.
    img_obj.source = img;  // we set the image source for our object.
}
img.src = 'img/filename.png'; // contains an image of size 256x16
                              // with 16 frames of size 16x16

function draw_anim(context, x, y, iobj) { // context is the canvas 2d context.
    if (iobj.source != null)
        context.drawImage(iobj.source, iobj.current * iobj.width, 0,
                          iobj.width, iobj.height,
                          x, y, iobj.width, iobj.height);
    iobj.current = (iobj.current + 1) % iobj.total_frames;
                   // incrementing the current frame and assuring animation loop
}

function on_body_load() { // <body onload='on_body_load()'>...
    var canvas = document.getElementById('canvasElement');
                 // <canvas id='canvasElement' width='320' height='200'/>
    var context = canvas.getContext("2d");

    setInterval((function (c, i) {
                return function () {
                    draw_anim(c, 10, 10, i);
                };
    })(context, img_obj), 100);
}

这是我解决问题的方法。希望这对你有所帮助。(已测试)


这有点老了。现在我处理它的方式会完全不同。如果您不介意在代码中添加新库,请使用这些评论中提供的众多可用替代方案之一。考虑到ES6的出现,这将更好地重构为一个具有更多功能的类。 :) - Adrian Castravete

2

对于那些仍然遇到问题的人,或者不想动态加载图像或弄清需要使用多少帧的人;

将动画GIF保留在HTML页面上,在CSS中设置为display:block、visibility:visible和position:relative。动态定位它在画布下面,用负边距/ z-index来控制位置。然后设置一个JavaScript计时器,重复调用drawImage,速度要足够快以便正确地刷新图像。

如果图像在DOM中不可见,则drawImage例程无法获取动画的后续帧。如果图像绝对定位在画布下方,则渲染会滞后。


除非您将多个画布叠放在一起,否则无法像这样进行分层。 - trinalbadger587
2
我认为Ayelis并没有提出多个画布层的建议。相反,将图像作为常规img标签加载到html层中(可以本地处理gif动画),并在其样式标签中使用z-index人为地将它们抬高到画布层之上。这种方法不适用于每种情况,因为你不能让画布元素“在它们之上”,但它可以用于始终处于“顶部”的显示组件。通过更改图像元素的html“top”和“left”设置,可以将图像在屏幕上移动。 - fmacdee
这是正确的。这是我在专业应用程序中使用的一种方法,以从动画GIF中提取帧并将它们“blit”到画布中。本质上,GIF隐藏在画布下面。它不能设置为不可见或屏幕外,因为否则帧将无法被提取,至少在Chrome实例和我在2014年测试代码的VTC1010上是如此。 - Ayelis

1
好的,就像其他人已经说过的那样,您需要将PE动画拆分成帧。我解决这个问题的方式更多是个人喜好,但我会在GIMP中打开GIF文件,并使用插件将所有显示为单独图层的帧转换为精灵表。然后我只需在画布上播放精灵,这要容易得多。

这里是链接的插件 :D


插件链接为404:https://www.gimp.org/registry/node/20943 - wyz

0
如果您已经在画布中编程了某种帧速率,那么将gif导出为一系列图像可能是一个不错的策略。

在Photoshop中,您可以打开gif(打开时间轴窗口),然后选择“文件>导出>渲染视频”,并选择“Photoshop图像序列”。

预加载它们全部,添加计数器,然后只需使用drawImage根据计数器绘制正确的图像即可。


-10

画布动画不是HTML5规范的一部分。要么回到GIF,要么考虑使用基于JavaScript的库来渲染SVG,或者回退到Canvas/VML:http://raphaeljs.com/


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