26
votes

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.

4
(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 (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 on how to restart a gif with JS.ashleedawg
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

4 Answers

33
votes

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.

2
votes
// 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.

1
votes

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.)

1
votes

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>