Jem Jem - 1 month ago 5
Javascript Question

Wait for image to be loaded before going on

I'm developing a game using JavaScript and

canvas
. As the game loads, all images that will be used are being cached.

Observing the resource timeline, I see that the following code triggers an asynchronous request:

var sprite = new Image();
sprite.src = "sprites/sheet1.png";


The engine will keep executing, eventually beginning to draw and play the level. Images that are loaded after the first frame is painted might never appear due to clipping (i.e. not getting "dirty").

So I tested the following:

console.log("begin");
var sprite = new Image();
sprite.onload = function() { console.log('loaded!'); };
sprite.src = "sprites/sheet1.png";
console.log("end");


The resulting console outputs in the order they occur are:


  • begin

  • end

  • loaded!



I'm looking for a similar way to
$.ajax
with
async: false
to perform the loading. Can't figure out how... thanks in advance for you help!
J.

Answer

You shouldn't make anything synchronous (not even AJAX) calls but instead simply put your code in the appropriate callback:

function loadSprite(src, callback) {
    var sprite = new Image();
    sprite.onload = callback;
    sprite.src = src;
}

Then use it like this:

loadSprite('sprites/sheet1.png', function() {
    // code to be executed later
});

If you want to pass additional arguments, you can do it like this:

sprite.onload = function() {
    callback(whatever, args, you, have);
};

If you want to load multiple elements and need to wait for all of them to finish, consider using the jQuery deferred object:

function loadSprite(src) {
    var deferred = $.Deferred();
    var sprite = new Image();
    sprite.onload = function() {
        deferred.resolve();
    };
    sprite.src = src;
    return deferred.promise();
}

In the function loading the sprites, you do something like this:

var loaders = [];
loaders.push(loadSprite('1.png'));
loaders.push(loadSprite('2.png'));
loaders.push(loadSprite('3.png'));
$.when.apply(null, loaders).done(function() {
    // callback when everything was loaded
});

http://api.jquery.com/jQuery.when/