Fire an event after preloading images

15,158

Solution 1

You can use the new "$.Deferred" if you like:

var preload = ["a.gif", "b.gif", "c.gif"];
var promises = [];
for (var i = 0; i < preload.length; i++) {
    (function(url, promise) {
        var img = new Image();
        img.onload = function() {
          promise.resolve();
        };
        img.src = url;
    })(preload[i], promises[i] = $.Deferred());
}
$.when.apply($, promises).done(function() {
  alert("All images ready sir!");
});

Might be a little risky to leave the Image objects floating around, but if so that could be fixed easily by shifting the closure. edit in fact I'll change it myself because it's bugging me :-)

Solution 2

Since your tags include jQuery, here's what I would do in jQuery, with heavy inspiration from this related answer:

function preloadImages(images, callback) {
    var count = images.length;
    if(count === 0) {
        callback();
    }
    var loaded = 0;
    $.each(images, function(index, image) {
        $('<img>').attr('src', image).on('load', function() { // the first argument could also be 'load error abort' if you wanted to *always* execute the callback
            loaded++;
            if (loaded === count) {
                callback();
            }
        });
    });
};

// use whatever callback you really want as the argument
preloadImages(["a.gif", "b.gif", "c.gif"], function() {
    alert("DONE");
});

This relies on the callback to jQuery's load function.

I wouldn't use the related answer simply because I don't like mucking around with Javascript's built-in prototypes.

Solution 3

I've seen something used to correct behavior on Masonry nice jQuery plugin (a plugin used to make nice layout composition on pages). This plugin had problems with blocks containing images and should delay his work when the images are loaded.

First solution is to delay on the onLoad event instead of document.ready. But this event can be quite long to wait for. So they use jquery.imagesloaded.js which can detect that all images in a div are loaded; especially this very short and nice code can handle cached images which does not fire the load event sometimes.

Solution 4

Today I needed to preload images and execute some code only after all images are loaded, but without jQuery and using Ionic2/Typescript2. Here's my solution:

// Pure Javascript Version
function loadImages(arrImagesSrc) {
    return new Promise(function (resolve, reject) {
        var arrImages = [];
        function _loadImage(src, arr) {
            var img = new Image();
            img.onload = function () { arr.push([src, img]); };
            img.onerror = function () { arr.push([src, null]); };

            img.src = src;
        }
        arrImagesSrc.forEach(function (src) {
            _loadImage(src, arrImages);
        });
        var interval_id = setInterval(function () {
            if (arrImages.length == arrImagesSrc.length) {
                clearInterval(interval_id);
                resolve(arrImages);
            }
        }, 100);
    });
}

// Ionic2 version
private loadImages(arrImagesSrc: Array<string>): Promise<Array<any>> {
    return new Promise((resolve, reject) => {
      ...
      function _loadImage(src: string, arr: Array<any>) {
        ...
      }
      ...
 }

You can use like this. Problematic url returns 'null'.

loadImages(['https://cdn2.iconfinder.com/data/icons/nodejs-1/512/nodejs-512.png', 'http://foo_url'])
.then(function(arr) {
   console.log('[???]', arr); 
})
Share:
15,158

Related videos on Youtube

Badr Hari
Author by

Badr Hari

Updated on October 05, 2020

Comments

  • Badr Hari
    Badr Hari over 3 years

    This is the code I use to preload images, I'm not sure if it's the best one. My question is, how can I fire and event, for an example alert(); dialog after is has finished loading all the images?

    var preload = ["a.gif", "b.gif", "c.gif"];
        var images = [];
        for (i = 0; i < preload.length; i++) {
            images[i] = new Image();
            images[i].src = preload[i];
        }
    
  • Badr Hari
    Badr Hari about 13 years
    Yes, it is a good technique, but I need to load HUGE files and I want to tell the user that they are loading and alert them when it's ready. It can't be done via CSS :)
  • Miquel
    Miquel about 13 years
    Well, if I am not mistaken the onLoad event will fire when all has been loaded so within the onLoad event handler you can advise the user that all the images have been loaded. If you need to tell the user when every image has finished then you need the onload event of the image object as has been suggested
  • Matt
    Matt about 13 years
    A bit off topic ... I'm curious what you meant by shifting the closure. What var were your closuring before?
  • Pointy
    Pointy about 13 years
    @Matt I had let the "img" variable be overwritten on each loop iteration; the closure was just around the onload callback. It would probably work that way, but it seemed like a bad thing to leave here for posterity :-)
  • Ben Clayton
    Ben Clayton almost 11 years
    Made a couple of small fixes to the code (was new'ing Image twice).
  • tmaximini
    tmaximini almost 11 years
    +1 for jquery.imagesloaded.js - I use it all the time in my projects.
  • Alex
    Alex over 10 years
    Using jQuery promises - this is great.
  • dotty
    dotty almost 10 years
    Hmmm, the line $.when.apply($, promises).done() doesn't seem to work in IE 7. Any ideas?
  • Pointy
    Pointy almost 10 years
    @dotty no I don't know why it wouldn't work; do you get errors?
  • dotty
    dotty almost 10 years
    Nope. No errors are thrown at all, it just seems to skip over it. I added an alert() to test it, and it never fired.
  • Pointy
    Pointy almost 10 years
    @dotty well are you sure that the images are loading? Also: make sure that you set up the "onload" handler before you set the "src" property.
  • Sk8erPeter
    Sk8erPeter almost 9 years
    You should paste the relevant information, not just throw in a link.
  • django
    django about 8 years
    check my jsfiddle. jsfiddle.net/bababalcksheep/ds85yfww If images dont exist we dont even get a callback ..
  • Sajjan Sarkar
    Sajjan Sarkar over 7 years
    @Pointy I seem to have a tiny glitch when I tried to use this code, have posted it as a separate question, if u get a min: stackoverflow.com/questions/39416666/…

Related