Stopping GIF Animation Programmatically
Asked Answered
L

4

84

I am developing a Twitter application which references to the images directly from Twitter. How can I prevent animated gifs from being played?

Using window.stop() at the end of the page does not work for me in Firefox.

Is there a better JavaScript hack? Preferable this should work for all browsers

Lawannalawbreaker answered 10/9, 2010 at 21:24 Comment(3)
If you have server side language at your disposal I think you better use server side code to take the first frame, store it on your server and show it instead..Chevron
The problem is that there are 15 to 60 images from twitter to change. See jetwick.com (open source).Lawannalawbreaker
yeah but you only change it once so it shouldn't be a problem.Chevron
L
66

This is not a cross browser solution but this worked in firefox and opera (not in ie8 :-/). Taken from here

[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);

function is_gif_image(i) {
    return /^(?!data:).*\.gif/i.test(i.src);
}

function freeze_gif(i) {
    var c = document.createElement('canvas');
    var w = c.width = i.width;
    var h = c.height = i.height;
    c.getContext('2d').drawImage(i, 0, 0, w, h);
    try {
        i.src = c.toDataURL("image/gif"); // if possible, retain all css aspects
    } catch(e) { // cross-domain -- mimic original with all its tag attributes
        for (var j = 0, a; a = i.attributes[j]; j++)
            c.setAttribute(a.name, a.value);
        i.parentNode.replaceChild(c, i);
    }
}
Lawannalawbreaker answered 25/11, 2010 at 11:53 Comment(7)
It's using HTML5 so as far as I can see, it should work on any browser supporting HTML5. According to this: deepbluesky.com/blog/-/browser-support-for-css3-and-html5_72 IE still does not support it.Chevron
I think this would only work on local animated gifs as opposed to those hosted on a different domainNativity
Library based on this answerEliza
There is something wrong with the script, isn't it? If .drawImage doesn't fail with an error, there is no CORS problem and catch branch won't execute. If, however there is a CORS issue, the script ends and whole try/catch is not reached. Am I right?Paprika
If I remember correctly, in IE8 gif elements have a stop function you can call to stop the animation.Hellas
On one hand, this is a solution from 2010. On the other hand, this worked for me nicely on Chrome (Windows 7). The fact that I mention also the OS is that suprisingly, it didn't work on Chrome based on Linux, for some reason. On my Chrome it changes the "src" of all the GIF files to binary (src="data:..."). On the Linux Chrome it changed everything to "canvas" and the images weren't displayed correctly on the page. Does anyone know why is that?Skyeskyhigh
@Nativity in response to that, it only fails for the is_gif_image filter, but the freezing works fine for example gifs imported via giphyReptile
T
76

Inspired by the answer of @Karussell I wrote Gifffer. Check it out here https://github.com/krasimir/gifffer

It automatically adds stop/play control on top of your Gif.

Tonitonia answered 19/6, 2014 at 18:43 Comment(6)
Wish I could +5 this.Samuele
Wish I could +5 the previous comment here... :) This is a great little (but very smart) piece of code for handling animated GIFs like that. ThanksSkyeskyhigh
I realize this is 3 1/2 years old. I don't care, that doesn't mean this still isn't outstanding. Plugged it into a page today, works beautifully.Deemphasize
If I may, why the extra g?Gastroenterology
@Gastroenterology I guess you are asking why the extra "f". I suppose "gifer" was taken already.Tonitonia
Please modify this answer so that it is not a link-only answer.Aldred
L
66

This is not a cross browser solution but this worked in firefox and opera (not in ie8 :-/). Taken from here

[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);

function is_gif_image(i) {
    return /^(?!data:).*\.gif/i.test(i.src);
}

function freeze_gif(i) {
    var c = document.createElement('canvas');
    var w = c.width = i.width;
    var h = c.height = i.height;
    c.getContext('2d').drawImage(i, 0, 0, w, h);
    try {
        i.src = c.toDataURL("image/gif"); // if possible, retain all css aspects
    } catch(e) { // cross-domain -- mimic original with all its tag attributes
        for (var j = 0, a; a = i.attributes[j]; j++)
            c.setAttribute(a.name, a.value);
        i.parentNode.replaceChild(c, i);
    }
}
Lawannalawbreaker answered 25/11, 2010 at 11:53 Comment(7)
It's using HTML5 so as far as I can see, it should work on any browser supporting HTML5. According to this: deepbluesky.com/blog/-/browser-support-for-css3-and-html5_72 IE still does not support it.Chevron
I think this would only work on local animated gifs as opposed to those hosted on a different domainNativity
Library based on this answerEliza
There is something wrong with the script, isn't it? If .drawImage doesn't fail with an error, there is no CORS problem and catch branch won't execute. If, however there is a CORS issue, the script ends and whole try/catch is not reached. Am I right?Paprika
If I remember correctly, in IE8 gif elements have a stop function you can call to stop the animation.Hellas
On one hand, this is a solution from 2010. On the other hand, this worked for me nicely on Chrome (Windows 7). The fact that I mention also the OS is that suprisingly, it didn't work on Chrome based on Linux, for some reason. On my Chrome it changes the "src" of all the GIF files to binary (src="data:..."). On the Linux Chrome it changed everything to "canvas" and the images weren't displayed correctly on the page. Does anyone know why is that?Skyeskyhigh
@Nativity in response to that, it only fails for the is_gif_image filter, but the freezing works fine for example gifs imported via giphyReptile
L
12

In an attempt to improve on Karussell's answer, this version should be cross-browser, freezes all images including those that have an incorrect file ending (e.g. automated image loading pages), and does not conflict with the function of the original image, allowing the original to be right clicked as if it were moving.

I would make it detect animation but that is much more intensive than just freezing them regardless.

function createElement(type, callback) {
    var element = document.createElement(type);

    callback(element);

    return element;
}

function freezeGif(img) {
    var width = img.width,
    height = img.height,
    canvas = createElement('canvas', function(clone) {
        clone.width = width;
        clone.height = height;
    }),
    attr,
    i = 0;

    var freeze = function() {
        canvas.getContext('2d').drawImage(img, 0, 0, width, height);

        for (i = 0; i < img.attributes.length; i++) {
            attr = img.attributes[i];

            if (attr.name !== '"') { // test for invalid attributes
                canvas.setAttribute(attr.name, attr.value);
            }
        }

        canvas.style.position = 'absolute';

        img.parentNode.insertBefore(canvas, img);
        img.style.opacity = 0;
    };

    if (img.complete) {
        freeze();
    } else {
        img.addEventListener('load', freeze, true);
    }
}

function freezeAllGifs() {
    return new Array().slice.apply(document.images).map(freezeGif);
}

freezeAllGifs();
Labial answered 11/7, 2014 at 21:47 Comment(0)
P
5

This is a bit of a hack, but you could try loading the gif into an iframe and calling window.stop() from inside the iframe (on itself) once the image has loaded. This prevents the rest of the page from stopping.

Pallmall answered 10/9, 2010 at 21:33 Comment(4)
will this slow down page rendering?Lawannalawbreaker
i don't think so, no. try it!Pallmall
Would you mind to give me a code example. I couldn't get it working with your method + see the updateLawannalawbreaker
calling window.stop() from inside the iframe will also stop the original window from being executed or how you would do this exactly?Lawannalawbreaker

© 2022 - 2024 — McMap. All rights reserved.