Tutorial: Loading Images with JavaScript

In preparation for the (still) upcoming Tetris tutorial, I decided to write a small tutorial for loading images with Javascript. This tutorial will show you how to build a bulk image loading utility that we will use to load the images for our HTML 5 Tetris game.

Open a new blank text document and save it as BulkImageLoader.js. Now create an empty function object and name the function BulkImageLoader as shown below.

function BulkImageLoader()
{

}

Now we'll add a few properties to our makeshift class. What sort of thing might be useful in a bulk image loading class? How about an array to store all the images? OK, that's obvious, what else? A value to track the number of images that have already been loaded would be nice and also a boolean value to tell us that all the images have been loaded and are ready for use. Easy enough, go ahead and add these properties as I've done below.

function BulkImageLoader()
{
    this.images = [];
    this.imagesLoaded = 0;
    this.isReady = false;
}

Next we need to start adding methods to our class. The first method we'll create will be called addImage. This function will simply add an image to our array so that we can load it later on. Add the following code below the class properties.

this.addImage = function (src, name) {
    var img 	= new Image();
    img.loader	= this;
    this.images.push( {image:img, source:src, imgName:name} );
};

This function takes in two parameters. The first is the image path or source. The second is a name that we may want to refer to this image by. The method creates a new image, sets up a loader property and assigns our class object to it (this will come in handy later on) and lastly we create a new generic object that contains the image, the image source and the image name and push that object onto our images array.

Our next task will be to write a function to actually load all the images. This function will simply loop through our images array and use the objects in that array to load each image. You can add this function just below the addImage function we created above.

this.loadImages = function() {
    for(var i = 0, len = this.images.length; i < len; i++)
    {
        this.images[i].image.src = this.images[i].source;			
        this.images[i].image.onload = this.onImageLoaded;
        this.images[i].image.name = this.images[i].imgName;
    }
};

As mentioned, the function loops through our array. The first line in the loop sets the image source and kicks off the actual loading process. After the source is set we add an onload callback method. Don't worry, you didn't miss anything, we just haven't written the onImageLoaded function yet; we'll take care of that in just a bit. The last line in the loop assigns the name to the image so that we have an easy way to access images if we want.

Now let's go ahead and create that onImageLoaded function that we used above. Again, just add this below the methods you've already created.

this.onImageLoaded = function() {
    this.loader.imagesLoaded++;
    this.loader.onProgressCallback();

    if(this.loader.imagesLoaded == this.loader.images.length)
    {
        this.loader.isReady = true;
        this.loader.onReadyCallback();
    }
};

This method is pretty simple. All we do is increment our imagesLoaded property by one, call a function we haven't written yet and then check to see if that number matches the length of our array. If it does, that means all the images have been loaded so we set the isReady boolean to true and also call another function we haven't written yet: onReadyCallback. That function is meant to be overwritten by the programmer so for now we're going to ignore it, but I'll come back to it before we're all done. We'll do the same with onProgressCallback as well.

At this point we have a way to add images to our loader, load those images and even know when all the images have finished loading. The next step is to grant access to those images through a couple of helpful methods. We'll add two new functions: getImageAtIndex and getImageByName.

this.getImageAtIndex = function(index) {
    return this.images[index].image;
};
	
this.getImageByName = function(name) {
    var img;
		
    for(var i = 0, len = this.images.length; i < len; i++)
    {
        if( this.images[i].imgName == name )
        {
            img = this.images[i].image;
            i = len;
        }
    }
		
    return img;
};

The first function just takes in an index and returns the image at that position in the array. This is fine for smaller projects, but the getImageByName function is going to be more useful if you have more than just a few images. This function allows you to ask for an image by name and its much easier to remember an image by name than it is to remember which position you loaded it at.

I promised we'd come back to that onReadyCallback method and now's the time to do that. As mentioned, this function should be overridden by the programmer and we want to enforce this; so by default, onReadyCallback will simply throw an error.

this.onReadyCallback = function() { 
    throw new Error("BulkImageLoader.onReadyCallback was not set"); 
};

The last thing we need to add is the onProgressCallback function. This could be useful when creating a proper preloader and you could also override it for increased functionality. In this version, we're just logging the result to the console. In an actual game, you'd probably want to use the progress result in a loading bar.

this.onProgressCallback = function() {
    var result;
    if(this.images.length > 0)
        result = this.imagesLoaded / this.images.length 
    else
        result = 0;

    console.log(result);			
    return result;
};

That's all for our BulkImageLoader class. The only thing left to do is show you how to use it! You can check out the code below to get an idea of how this works and to see things in action, have a look at this simple example. Right click the page and view source to see the code. Alternatively, you can download the sample project at the end of this tutorial.

window.onload = onReady;

var imgLoader;

function onReady() {

    imgLoader = new BulkImageLoader();
    imgLoader.addImage("./images/spider.jpg", "spider");
    imgLoader.addImage("./images/canopy.jpg", "canopy");
    imgLoader.addImage("./images/hawaii.jpg", "hawaii");
	
    imgLoader.onReadyCallback = onImagesLoaded;
	imgLoader.loadImages();
}

function onImagesLoaded() {
    // access the images
    imgLoader.getImageByName('spider');
    imgLoader.getImageByName('canopy');
    imgLoader.getImageByName('hawaii');
}

Good stuff! That's all there is to it. In this tutorial you learned how to build a bulk image loader class using Javascript. This will be a very useful utility class in pretty much every HTML 5 game you create so keep it handy! Feel free to chime in with your own thoughts or comments if you've got another way of doing things. As always, thank you for reading!

Download Example

Bookmark and Share

Leave a Reply

Subscribe to RSS feed FGS5 Badge