ARTICLE AD BOX
I have a case for a web-site simple slide-show. The basic implementation is a collection of html IMG objects which start out hidden. In sequence, each IMG object has an image loaded into it, and shown, as the previous one is hidden.
My requirement is for a minimal implementation without using any external code or libraries or frameworks. I also don't want any transition effects or anything, one goal is to have the images switch smooth enough to be nearly like video (but no more than 8 FPS or so), while using minimal CPU on the client.
What I have does work in Chrome (and related browsers), but does not work in Firefox. And by "does not work", I mean, that while the pictures show in sequence, the display flickers (to the point where any speed faster than about 1200 ms is painful to the eye). I figure that the right way of doing this is to set the src property, and set the onload handler, so that the images get switched upon successful load. For contrast, I've also tested using the "naive" strategy of setting the src property, and then switching the visibility immediately. If I use the wrong "naive" strategy, the display flickers, and this happens in all browsers, as is predictable. However, using a more correct strategy (hooking onload), this works correctly in Chrome, but not in Firefox. Firefox flickers just as if I used the "naive" strategy. I've also tried this using the display style ("inline" vs "none") rather than visibility, and everything works and doesn't work the same way.
I guess maybe that this is either a bug in Firefox, or I'm doing something wrong, which Chrome is fixing for me. But that's the question.
Here are some code excerpts to be clear about what I'm doing:
var ix = 2; function thing() { let previous = document.getElementById("pic" + (ix - 1)); let img = document.getElementById("pic" + ix); let url = "out" + ix + ".jpg"; // this is the naive way of doing things, and it's horribly wrong and doesn't work if (true) { // start loading the image, switch to it immediately, and hope the browser gods will untangle it all img.src = url; img.style.visibility = "visible"; previous.style.visibility = "hidden"; } ix += 1; window.setTimeout(thing, 150); } thing(); // alternative 1. this is where I started, and I expected it to work if (true) { // start loading the new image, but don't switch until it's loaded img.onload = function() { img.onload = null; img.style.visibility = "visible"; previous.style.visibility = "hidden"; }; img.src = url; } // alternative 2. I found a reference to the decode method, so I thought I'd try it if (true) { // start loading the new image, but don't switch until it's decoded img.src = url; // decode is supposed to return a promise for completion img.decode().then(function() { img.style.visibility = "visible"; previous.style.visibility = "hidden"; }); }If you want to see it easily in action, I have set up a minimal demonstration here: https://halo.hamstertoad.org/public/wwinton/specific/slideshow_vs_firefox/index.html?mode=onload&delay=333 . also, here's the same thing, using the "wrong" mode: index.html?mode=wrong. The code adds some query-string garbage to the jpg references to prevent the browser cache from confusing things (I also tested without to ensure no tainting of result).
EDIT 1: This example does not even require a web server. Place all the image files and the index html in any local directory, and point firefox at it, and the same flicker happens.
I found that there is a decode method which returns a Promise, and I was hoping that it would do things somewhat differently, but it looks like it works out the same way the onload handler does.
So, is this a bug in Firefox where there is no workaround and all users are just doomed, or is this something stupid I'm doing, or is there a workaround ? (other than using Chrome, anyway)
