How do image preloaders work?

Loading a single image

The browser will load images asynchronously…meaning when the browser is given the .src of an image, it will start loading that image in the background, but will also continue processing the javascript code directly after .src

// create a new image object
var img=new Image();

// set the image object's image source
img.src="https://stackoverflow.com/questions/30578521/myImage.png";

// do some stuff while the image is loading in the background
alert('Your image has started loading, but is not yet complete');

The alert will display even before the image is fully loaded and ready to use.

So how do you know when the image is fully loaded and ready to use?

Answer: You can tell the browser to “call you back” when it finishes loading the image. You get “called back” by adding an “img.onload” function on the image object. Whenever the browser finishes loading the image, the browser will trigger the code in the “img.onload” function.

img.onload = theImageHasFinishedLoading;

function theImageHasFinishedLoad(){
    alert('Your image has finished loading...you can use it now');
}

The complete image loading process will occur in this sequence:

// happens 1st
var img=new Image();

// happens 2nd: this callback is ASSIGNED, but NOT TRIGGERED yet
//     until the image has fully loaded
img.onload = theImageHasFinishedLoading;

// happens 3rd
img.src="https://stackoverflow.com/questions/30578521/myImage.png";

// happens 4th
alert('Your image has started loading, but is not yet complete');

// happens 5th after the browser has fully loaded the image
//     (The browser will call this function automatically because .onload was set)
function theImageHasFinishedLoad(){
    alert('Your image has finished loading...you can use it now');
}

Pre-loading multiple images

To preload multiple images:

  • Create an array to hold all your image URLs and add your image URLs to this array.

    // For example
    var imageURLs=[];
    imageURLs[0]="https://stackoverflow.com/questions/30578521/myImage.png";
    
  • Create an array to hold all your image objects (==your actual images).

    // For example
    var imgs=[];
    
  • Add new Image elements to the image object array (add one new Image for each URL in the URL array).

    //For example
    imgs[0] = new Image();
    
  • Set every image object’s .onload callback to the same function.

    // For example
    imgs[0].onload = theImageHasFinishedLoading;
    
  • Use the image URL array to set the .src of each image to the individual url.

    // For example
    imgs[0].src = imageURLs[0];
    
  • In the theImageHasFinishedLoading callback, increment a counter every time a new image is successfully loaded.

    // For example
    var counter=0;
    
    function theImageHasFinishedLoading(){
        counter++;
    }
    

You will know that all images are fully loaded when the counter reaches the same length as your image URL array.

    function theImageHasFinishedLoading(){
        counter++;
        if(counter>=imageURLs.length){
            alert('All the images have successfully preloaded. Go use them now!');
        }
    } 

Here’s a full example code and a Demo:

window.onload=(function(){


  // canvas related variables
  var canvas=document.getElementById("canvas");
  var ctx=canvas.getContext("2d");
  var cw=canvas.width;
  var ch=canvas.height;

  // put the paths to your images in imageURLs[]
  var imageURLs=[];  
  imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/face1.png");
  imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/face2.png");

  // the loaded images will be placed in imgs[]
  var imgs=[];
  var imagesOK=0;
  startLoadingAllImages(imagesAreNowLoaded);

  // Create a new Image() for each item in imageURLs[]
  // When all images are loaded, run the callback (==imagesAreNowLoaded)
  function startLoadingAllImages(callback){

    // iterate through the imageURLs array and create new images for each
    for (var i=0; i<imageURLs.length; i++) {
      // create a new image an push it into the imgs[] array
      var img = new Image();
      // Important! By pushing (saving) this img into imgs[],
      //     we make sure the img variable is free to
      //     take on the next value in the loop.
      imgs.push(img);
      // when this image loads, call this img.onload
      img.onload = function(){ 
        // this img loaded, increment the image counter
        imagesOK++; 
        // if we've loaded all images, call the callback
        if (imagesOK>=imageURLs.length ) {
          callback();
        }
      };
      // notify if there's an error
      img.onerror=function(){alert("image load failed");} 
      // set img properties
      img.src = imageURLs[i];
    }      
  }

  // All the images are now loaded
  // Do drawImage & fillText
  function imagesAreNowLoaded(){

    // the imgs[] array now holds fully loaded images
    // the imgs[] are in the same order as imageURLs[]

    ctx.font="30px sans-serif";
    ctx.fillStyle="#333333";

    // drawImage the first image (face1.png) from imgs[0]
    // and fillText its label below the image
    ctx.drawImage(imgs[0],0,10);
    ctx.fillText("face1.png", 0, 135);

    // drawImage the first image (face2.png) from imgs[1]
    // and fillText its label below the image
    ctx.drawImage(imgs[1],200,10);
    ctx.fillText("face2.png", 210, 135);

  }



}); // end window.onload
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=200></canvas>

Leave a Comment