29

I am creating a slideshow of animations using animated GIFs. I'm crossfading from one animation to the next. The problem is: the only way I have discovered to ensure that the GIF starts animating from the first frame is to reload it each time it's shown. The GIFs are 200KB or so each, which is way too much bandwidth for a continuous slideshow.

Here's my current code. img and nextimg are <div> tags containing a single <img> each. nextimg_img is the <img> tag corresponding to the next image to be displayed.

var tmp = nextimg_img.attr('src');
nextimg_img.attr('src', '');
setTimeout(function() { nextimg_img.attr('src', tmp); }, 0);
img.fadeOut('slow');
nextimg.fadeIn('slow');

The idea is that it sets the src attribute of the next image to '', then sets it back to the source of the GIF to be displayed.

This works — it restarts the animation from the beginning — but the GIFs seem to be redownloaded every time they are displayed.

EDIT: it's a looping slideshow, and I'm trying to avoid reloading the GIFs from the net when they get shown the second/third/subsequent time.

ashleedawg
  • 20,365
  • 9
  • 72
  • 105
nornagon
  • 15,393
  • 18
  • 71
  • 85
  • *(old question but....)* If I understand properly, you just want the GIF to loop indefinitely? if so, you don't need to do it programmatically; you just set the gif's "repeat" value to `0` to repeat "indefinitely". You can do this with an online tool like [ezGIF.com](https://ezgif.com/split) (upload the gif and then click "frames" to change the "loop" value to `0`). If that's not the issue, I also added an answer [below](https://stackoverflow.com/a/64017942/8112776) on how to restart a gif with JS. – ashleedawg Sep 22 '20 at 21:32
  • That is not what I was asking in this question. I was asking how to start a GIF animation from the beginning whenever it is shown. – nornagon Sep 22 '20 at 22:48

4 Answers4

36

You should preload your images into code.

var image = new Image();
image.src = "path";

when you want to use:

nextimg_img.attr('src', image.src);

Then when you swap the src out just swap from the preloaded image objects. That should do the trick to avoid redownloading.

spinon
  • 10,760
  • 5
  • 41
  • 59
  • Will that start the GIF animation from the beginning? – nornagon Jul 07 '10 at 04:35
  • I don't see why it wouldn't. As I imagine that the animation doesn't actually start till it is being displayed on the screen. But I honestly haven't tried before so I can't say with 100% certainty. – spinon Jul 07 '10 at 04:37
  • 1
    Ah, you're right -- I'm missing one detail. It's a looping slideshow. So when the GIFs come back up again, they're halfway through their animation unless I reload them. – nornagon Jul 07 '10 at 04:42
  • 2
    That's interesting. Not sure if that affects this. Though if you are hiding the images vs removing them from the dom that would make a difference. I would say after you fade them out you should do a remove as well of the objects so it is removed from the dom. Then when you reload the image using the preloaded images it shouldn't matter. – spinon Jul 07 '10 at 04:45
  • Hm, this doesn't seem to work. The images keep animating even when they're not in the DOM. – nornagon Jul 07 '10 at 05:00
  • Can you post some sample code or point me to a page I could look at? I would have that removing that from the DOM and then adding a new one would have done it. – spinon Jul 07 '10 at 05:03
  • Oh, adding a new Image()? I was just adding the preloaded image back to the dom... – nornagon Jul 07 '10 at 05:07
  • No I meant adding div back and then setting the image to the gif. Let me check it out. You might be right. You might have to download from internet each time so that it will force replay. It's hard to say because each browser controls animated gifs differently. Let me check out your page. – spinon Jul 07 '10 at 05:09
  • I thought I just saw a link to a page. Did you remove that comment? – spinon Jul 07 '10 at 05:09
  • Ok so can you give me a rundown of what I am looking at and what you are expecting to see happen? – spinon Jul 07 '10 at 05:18
  • Crossfading from one GIF to the next. What should happen: each time a GIF appears, it should start animating from the first frame. What is happening: when a GIF appears, it's starting from some non-first frame. (in Chrome on OSX, anyway) – nornagon Jul 07 '10 at 05:20
  • ok I see similar in Safari on OSX but not what I see in IE on Win7 – spinon Jul 07 '10 at 05:26
  • hm, on closer inspection -- it seems like the first way of doing it does actually work, and doesn't redownload the images. At least, it doesn't any more. :S – nornagon Jul 07 '10 at 06:12
  • ok cool. Because I think you are just out of luck with safari because I have tried a few different things and it seems to always be a problem in safari. Wish I could have helped more. Sorry. – spinon Jul 07 '10 at 06:15
  • This seems to work as requested with newer Safari on OS X: http://jsfiddle.net/nilloc/A2fuZ/9/#base – Nilloc Jun 03 '14 at 20:32
  • Although Nilloc's demo works with an onClick event, this restart trick does not work when you want to restart a gif inside of another element that get's toggled hidden/visible. Example: http://jsfiddle.net/xLh5wsxd/1/ – Sverrir Sigmundarson Aug 15 '15 at 18:17
  • Edit: Actually the example in my comment above works sometimes but not reliably. However when swapping out the gif for a larger one it stops working all together. The restarting seems to depend on the size of the gif. Here is a link to the same example as above but with a bigger gif, showing how this doesn't work: http://jsfiddle.net/xLh5wsxd/2/ – Sverrir Sigmundarson Aug 15 '15 at 18:21
  • 2
    Finally here is a fiddle showing a workaround, random fake querystring causes a re-downloads always. Regardless of size: http://jsfiddle.net/xLh5wsxd/3/ – Sverrir Sigmundarson Aug 15 '15 at 18:29
  • This doesn't work if gif is inside a tooltip. – Rasmus Nov 22 '21 at 10:25
3

Next answer works only if your .gif image is located on your server or severs that provide Access-Control-Allow-Origin: * header in response, due to Cross-Origin limitation.

I use built-in fetch() to download gif to memory blob. Then this blob is used to update .src attribute of img element whenever you need to restart animation. As blob is kept in-memory it is not re-downloaded. Also to restart animation you just need to update .src attribute with same value again.

If fetch() is not supported by target browser then good-old XMLHttpRequest may be used. Also URL.createObjectURL() may be named differently then wrapper like here can be used.

Code below may also be tested on jsfiddle.

<input id="btn" type="button" value="ReStart">
<img id="img" height="150">
<script>
    document.addEventListener('DOMContentLoaded', ()=>{
        // fetch works only with urls on same server or servers that provide header "Access-Control-Allow-Origin".
        fetch('https://api-project-268277679120.appspot.com/h80bm5vc4iw7?url=https://i.stack.imgur.com/SkGeh.gif')
            .then(r=>r.blob())
            .then(b=>URL.createObjectURL(b))
            .then(u=>{
                document.getElementById('img').src = u;
                document.getElementById('btn').onclick = ()=>{
                    document.getElementById('img').src = u;
                };
            });
    });
</script>
Arty
  • 14,883
  • 6
  • 36
  • 69
1
// reset a gif in javascript
img.src = "your_image_url.gif"+"?a="+Math.random();

Tada!

Please note the GIF will be downloaded every time so keep it a small file.

Alvaro Silvino
  • 9,441
  • 12
  • 52
  • 80
1

This is a single-loop 5-frame GIF (eg., repeat=1).

As long as it's the only instance of that GIF on the page, then it can be restarted as needed (manually or on timer, etc). If it's not the only one, all instances will restart together.

const gif=document.getElementById('gif');

function restartGIF(){
   gif.src=gif.getAttribute('src');
}

function startTimer(){
  gif.src=gif.getAttribute('src');
  setTimeout(function(){ restartGIF() }, 10000);
}
<button onclick="restartGIF()">restart gif</button>
<br>
<button onclick="startTimer()">start every 10s</button>
<br>
<img id='gif' src='https://i.stack.imgur.com/VBKe6.gif'>

(Based on Spinon's accepted answer.)

ashleedawg
  • 20,365
  • 9
  • 72
  • 105