Animated GIF in HTML5 canvas
Asked Answered
L

6

55

In HTML5, how can I draw easily (no too much complex code please) an animated GIF in a canvas that works (with drawImage only first frame is shown in the canvas)

Lode answered 17/6, 2010 at 13:56 Comment(2)
This may be useful: github.com/matt-way/gifuct-jsWeatherglass
Another lib that might be worth a look: github.com/benwiley4000/gif-framesWeatherglass
W
17

I believe you are looking for http://slbkbs.org/jsgif

Unfortunately, the DOM doesn't expose individual frames of a GIF, so this is done by downloading the GIF (with XMLHttpRequest), parsing it, and drawing it on a <canvas>.

Werner answered 16/5, 2011 at 12:35 Comment(0)
R
17

Well if automated canvas animation of gif files isn't available, you could try using sprite-sheets, but that indeed would require a bit more code.

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

This is how I'd tackle the problem. Hope this has been helpful. (tested)

Ranson answered 16/4, 2012 at 19:11 Comment(1)
This is kind of old. The way I'd tackle it now would be way different. If you don't mind adding a new library to your code use one of the many available alternatives suggested in these comments. Taking into account the advent of ES6 this would more nicely be reconstructed as a class with a lot more functionality. :)Ranson
K
2

For anyone still having trouble with this, or those who don't want to load their images dynamically or figure out how many frames they need to use;

Leave the animated GIF on the HTML page, set to display:block, visibility:visible, and position:relative in the CSS. Dynamically position it under the canvas with a negative margin-top/z-index (or what have you). Then set a JavaScript timer that calls drawImage repeatedly, as fast as you need in order to refresh the image properly.

If the image is not visible in the DOM, the drawImage routine cannot acquire subsequent frames of the animation. If the image is absolutely positioned under the canvas, the rendering lags.

Kirimia answered 3/10, 2014 at 18:34 Comment(3)
You can't do layering like this unless you put multiple canvas (s) on top of each otherConsecution
I don't think Ayelis was proposing multiple canvas layers. Rather have the images loaded into the html layer as regular img tags (which can handle gif animations natively) and artificially raise them above the canvas layer using z-index in their style tags. This won't work for every situation since you can't have canvas elements "above them" but it can work for display components that are always "on top". You can move the image around the screen by changing the html "top" and "left" settings of the image element.Reubenreuchlin
That is correct. This was a method I used in a professional application in order to pull frames from an animated GIF and "blit" them into a canvas. Essentially the GIF is hiding beneath the canvas. It can't be set invisible or offscreen because the frames won't get pulled otherwise, at least in the Chrome instance and on the VTC1010 upon which I tested the code, back in 2014.Kirimia
X
1

Well, as other people said already, you have to split pe animation in frames. My way of tackling the problem is more of a personal preference, but I open the GIF in GIMP and using a plugin I convert all the frames which are displayed as individual layers into a sprite sheet. Then I only have to animate the sprite in the canvas which is much easier.

Here is the link for the plugin :D

Xena answered 14/11, 2016 at 14:42 Comment(1)
Link to the plugin is 404: gimp.org/registry/node/20943Baxy
S
0

If you already have programmed some kind of framerate into your canvas, it could be a good strategy to export the gif as a sequence of images.

In Photoshop you can open the gif (turn on timeline window) and then "File > Export > Render Video" and select "Photoshop Image Sequence".

Preload them all, add a counter and then just use drawImage to draw the correct image according to the counter.

Stableman answered 25/3, 2022 at 21:23 Comment(0)
A
-10

Canvas animation is not part of the HTML5 spec. Either revert to GIF or consider a JavaScript-based library that renders SVG or falls back to Canvas/VML: http://raphaeljs.com/

Appulse answered 17/6, 2010 at 21:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.