4

I'm trying to make a gif restart when the user clicks on it, without having to reload it (my gif is too heavy for that, I actually preload it for my application). My current code works perfectly on Chrome and all "modern browsers", but I need that to work in IE11 as well, and that's where the struggle begins.

Here is a sample code, that works perfectly on Chrome but not on IE11:

function activate_gif(){
    document.getElementById("img1").src = "https://i.imgur.com/Rsc0qOw.gif";
}
.myDiv{
  width: 500px;
  height: 300px;
}

.myDiv img{
  width: 100%;
  height: 100%;
}
<button onclick="activate_gif()">
  Click me
</button>
<div class="myDiv">
  <img id="img1" src="https://i.imgur.com/Rsc0qOw.gif">
</div>

You can also find it on this jsFiddle: https://jsfiddle.net/c6hodyh2/3/

You can find an other (not) working example of the problem (perfect with Chrome, not working with IE): https://codepen.io/InSightGraphics/pen/CAlci

What I've tried so far

Attempt 1

From this SO question, I tried the following JS code, to "force" the cache to refresh:

function activate_gif(){
    document.getElementById("img1").src = "";
    document.getElementById("img1").src = "https://i.imgur.com/Rsc0qOw.gif";
}

Result: No success, it had absolutely no different effect from my original code.

Attempt 2

From this article, I tried to refresh the innerHTML content:

function activate_gif(){
    document.getElementById("img1").style.display = '';
    document.getElementById("img1").innerHTML = document.getElementById("img1").innerHTML;
}

Result: No change in IE, and it stopped working in the other browsers, so I suppose it triggered a console error.

Attempt 3

From this SO question, I tried to use a simplified version of the solution, basically by forcing the image to be loaded again by adding a random suffix to its source URL:

function activate_gif(){
    document.getElementById('myImg').src = 'mysrc.gif?' + Math.random();
}

Result: This reloads the gif, which solves the cache problem by itself. However, the gifs I use in my real-life application are too heavy, so if the image is to be downloaded everytime the user presses the button, it results in a poor user experience, especially for those with a weaker bandwidth.

Attempt 4

From @IStepashka's answer, I tried to first set a (random and found on the web) blank image before setting back my original source:

function activate_gif(){
    document.getElementById("img1").src = "https://i.ytimg.com/vi/f3cLOucMpD0/maxresdefault.jpg";
    document.getElementById("img1").src = "https://i.imgur.com/Rsc0qOw.gif";
}

Result: Same as attempt 1, it didn't change anything. My code is still working on Chrome, but not on IE.

Reyedy
  • 918
  • 2
  • 13
  • 36

3 Answers3

2

It might be more appropriate to convert GIF file to a video and use <video> HTML tag. See Replace Animated GIFs with Video article by Jeremy Wagner. But if you want to stick to GIF you can utilize XMLHttpRequest, Blob and object URL given CORS and cache related HTTP headers are appropriately configured:

function activate_gif(){
    var url = "https://i.imgur.com/Rsc0qOw.gif";
    var img = document.getElementById( "img1" );

    var xhr = new XMLHttpRequest();
    // Browser will take cached response if it has cache entry with url key.
    xhr.open( "GET", url );
    xhr.responseType = "blob";
    xhr.onload = function() {
        if ( xhr.status != 200 ) {
            // Complain.
            return;
        }
        var blobUrl = URL.createObjectURL( xhr.response );
        img.src = blobUrl;
        setTimeout( function () {
            // Let browser display blob and revoke blob after stack unwind.
            URL.revokeObjectURL( blobUrl );
        }, 0 ); // You might need to increase delay time for large images.
    };
    xhr.send();
}
.myDiv{
  width: 500px;
  height: 300px;
}

.myDiv img{
  width: 100%;
  height: 100%;
}
<button onclick="activate_gif()">
  Click me
</button>
<div class="myDiv">
  <img id="img1" src="https://i.imgur.com/Rsc0qOw.gif">
</div>

You can also use browser detection to use more efficient and simpler code in other user agents.

For more information check:

Leonid Vasilev
  • 11,910
  • 4
  • 36
  • 50
  • Hi, thanks for your answer! The result looks amazing, I think that's what I'm looking for. If I understand well, the XMLHttpRequest takes the image from cache if it exists (meaning there is no extra downloading time), and then you create a new URL object, which is then interpreted as a new image (meaning it restarts the gif). Am I correct? – Reyedy May 18 '18 at 07:32
  • 1
    Yes, if cache entry exists and if it is fresh there will be no network request. Loading from a disk cache will take some time too though. Although this code snippet works on my test page in Firefox, it doesn't work in Stack Overflow code snippet for some reason. But I would probably use simpler and more efficient code in other browsers anyway. – Leonid Vasilev May 18 '18 at 08:03
  • Your snippet works for me on both Chrome and IE. And yeah, I implemented this solution only with IE and Edge anyway. It works perfectly well on my application. Thanks a lot for your help! – Reyedy May 18 '18 at 08:05
  • See the update with a solution using HTML ` – Leonid Vasilev Jun 16 '18 at 18:46
0

Try to first set any blank image to source and the get back your original source image. like that:

function activate_gif(){
    document.getElementById("img1").src = "images/blank.jpg"     
    document.getElementById("img1").src = "https://i.imgur.com/Rsc0qOw.gif";

}
iStepashka
  • 302
  • 1
  • 6
  • Hi, thank you for your answer. Unfortunately, I tried your solution and it doesn't change anything to the result, it's still not working in IE... :/ – Reyedy May 15 '18 at 08:06
  • Wotrh to try though. On ie edge it worked for me like charm – iStepashka May 15 '18 at 09:53
0

It seems that IE 11 will not actually replay a (non-looping) gif, if it has it in cache, and all instances of a same-src gif are actually synchronized… It seems like another of IE's... Erm, let's call them quirks.

Here is a (sad) workaround. It does reload the gif, but at least it pre-reloads it in the background so as to not have too much of an impact on user xp. I changed your gif to a 2MO+ one to show the background loading.

Please note that this should be only used on IE, since other browser work well with the simple solution.

var oldNode = document.getElementById("img1"),
    src = oldNode.src + "?bust=",
    nextNode = oldNode.cloneNode(),
    parent = oldNode.parentNode;
nextNode.src = src + new Date().getTime();
function activate_gifIE(){
  oldNode.removeNode();
  parent.appendChild(nextNode);
  oldNode = nextNode;
  nextNode = oldNode.cloneNode();
  
  nextNode.src = src + new Date().getTime();
}
.myDiv{
  width: 500px;
  height: 300px;
}

.myDiv img{
  width: 100%;
  height: 100%;
}
<button onclick="activate_gifIE()">
  Click me
</button>
<div class="myDiv">
  <img id="img1" src="https://media.giphy.com/media/LRVnPYqM8DLag/giphy.gif" height="200px">
</div>

I have seen workarounds such as this one and that one, but they involve looping gifs, and overlaying a still frame in front of them, or replacing them with it. Also on IE 11, you would have to settle for the user landing at a random time in the gif, because you can't seem to get it to replay…

Anyway, hope it helps.

Boris
  • 1,161
  • 9
  • 20