69

Is it possible to use javascript to control which frame of a GIF image is showing and/or stop the animation. I want to be able to load a GIF with several frames and only show one of them.

I know I could do it with lots of separate images, but if I can do what I want with a GIF, it will only be one file to worry about.

cнŝdk
  • 28,676
  • 7
  • 47
  • 67
Logan
  • 957
  • 2
  • 8
  • 10
  • 4
    You can also do it with one big image with sprites and only show exact sprite by clipping image – MBO Mar 05 '10 at 07:40
  • 1
    Agree with @MBO, with sprites is fairly simple, check this related question: http://stackoverflow.com/questions/1736922/how-to-show-animated-image-from-png-image-using-javascript-like-gmail – Christian C. Salvadó Mar 05 '10 at 07:45
  • Use video without sound. just like 9gag – atilkan Sep 08 '16 at 13:25
  • I think the short answer is no. If you want to use JavaScript, you’re most likely alternatives are controlling genuine video or using CSS sprites. The benefit of using CSS sprites is that you end up transferring a single image, and that image has better overall compression than multiple individual images. – Manngo Apr 05 '20 at 23:52

4 Answers4

63

You can use the libgif library.

It allows you to start/stop the gif and control which frame the gif is on.

<script type="text/javascript" src="./libgif.js"></script>
<img src="./example1_preview.gif" rel:animated_src="./example1.gif"
 width="360" height="360" rel:auto_play="1" rel:rubbable="1" />

<script type="text/javascript">
    $$('img').each(function (img_tag) {
        if (/.*\.gif/.test(img_tag.src)) {
            var rub = new SuperGif({ gif: img_tag } );
            rub.load(function(){
                console.log('oh hey, now the gif is loaded');
            });
        }
    });
</script>

(most of the code is taken directly from their example)

cнŝdk
  • 28,676
  • 7
  • 47
  • 67
Charlotte
  • 1,193
  • 1
  • 13
  • 21
  • This code doesn't seem to work for me. It plays the gif with `sup1.load()`, then when the gif is done, it goes to the first frame with `sup1.move_to(frame)`. I also tried using `pause()` but it didn't seem to freeze the gif on the first frame either. I edited the original code so that it stops on the first frame, but is there a way to pause the gif on the first frame without editing the code? – Leo C Han Dec 29 '14 at 02:42
  • @LeoCHan I've updated the example code to the latest api, try it now – Charlotte Apr 13 '15 at 19:08
  • 2
    This answer adresses the question a lot better than the acccepted one. – Wortex17 May 03 '15 at 12:15
  • I must be missing something here. What is the $$ ? I get undefined. – Rob L Dec 22 '15 at 02:42
  • To make this work with jQuery, `$$` should be `$` or `jQuery`, don't pass `img_tag` to the anonymous function, and simple use `this` in the function, instead of `img_tag` – Capsule Aug 15 '16 at 03:16
  • On latest chrome all their examples fail for me. – John Oct 29 '17 at 03:31
  • 1
    Very important to note the caveat in this library's fine print. `Caveat: same-domain origin. The gif has to be on the same domain (and port and protocol) as the page you're loading.` – Albert Renshaw Mar 22 '18 at 00:51
29

I use x-gif it's pretty cool and easy to setup.

From Github:

<x-gif src="probably_cats.gif"></x-gif>

Where you can add the following as attributes:

  • Playback modes:
    • speed="1.0" (default mode) multiplies the speed by the value of the attribute;
    • sync defers playback to an external object;
    • bpm="120" syncs GIFs to a given beats-per-minute;
  • Options:

    • stopped prevents the GIF from animating;

    • fill causes the GIF to expand to cover its container;

    • n-times="3.0" (speed mode only) stops playback (by adding the attribute stopped) after a set number of times;
    • snap (sync & bpm modes only) instead of allowing longer GIFs to sync to multiple beats, force them to fit into only one;
    • ping-pong plays the GIF front-to-back then back-to-front;
  • Debugging:
    • debug turns on debug output from the Gif Exploder;
    • exploded stops playback, and renders each frame out side-by-side.
cнŝdk
  • 28,676
  • 7
  • 47
  • 67
Oscar Nevarez
  • 835
  • 10
  • 22
  • From their [Github](https://github.com/geelen/x-gif) page it works like this ``: you can add several attributes to this tag with playback modes, options and debugging. I tried to edit your answer providing a [summary with them](http://stackoverflow.com/review/suggested-edits/9071628), but it was rejected, if you have the time, you can edit it yourself. – Armfoot Aug 06 '15 at 19:48
22

If you are OK with converting your gif to a sprite sheet, you can do it this way (using ImageMagick):

montage animation.gif -coalesce -tile x1 -geometry +0+0 -background None -quality 100 spritesheet.png

It is even likely that the new image will be of lesser size.

Once you have a sprite sheet, use CSS animation. An animation with a fixed frame time is used here:

var el = document.getElementById('anim');
function play() {
  el.style.animationPlayState = 'running';
}
function pause() {
  el.style.animationPlayState = 'paused';
}
function reset() {
  el.style.animation = 'none';
  el.offsetHeight; /* trigger reflow to apply the change immediately */
  el.style.animation = null;
}
function stop() {
  reset();
  pause();
}
#anim {
  background-image: url('https://i.stack.imgur.com/J5drY.png');
  width: 250px;
  height: 188px;
  animation: anim 1.0s steps(10) infinite;
}
@keyframes anim {
  100% { background-position: -2500px; }
}
<div id="anim" title="Animated Bat by Calciumtrice"></div>
<button onclick="play()">Play</button>
<button onclick="pause()">Pause</button>
<button onclick="reset()">Reset</button>
<button onclick="stop()">Stop</button>

If you want the animation to not start automatically, add paused to the end of animation rule.

user
  • 16,328
  • 6
  • 89
  • 89
  • 2
    This is an awesome and simple way to solve this problem, gratz! – rafaelcastrocouto Sep 01 '17 at 17:25
  • This method worked for me; it's easy to implement and adjust to your liking. I used ezgif here to create my sheet: https://ezgif.com/gif-to-sprite – ZontarZon Oct 10 '19 at 13:33
  • I know this is an old question and answer, but I have a question. I like this answer a lot and I would like to know if you can hide or make the animated GIF disappear and then reappear with this answer. – ThN May 14 '21 at 14:37
10

You can do it with a single image using CSS sprites.

N 1.1
  • 12,004
  • 6
  • 39
  • 57
  • 4
    This is true so long as what one wants to do is split up different variations of an image around the 2D plane, and not to split it up as separate frames. – Pointy Mar 05 '10 at 08:11