BenM
BenM

Reputation: 4278

Odd bug with drawImage on HTML5 canvas

JsFiddle (note: It doesn't show anything, it's merely a way for me to show my code in a neater format) http://jsfiddle.net/h6tVR/

I am new to HTML5 canvas and have decided to play about and see what I can do with it. So far I've been able to draw a locally hosted image onto the canvas and even do a bit of basic tiling:

window.onload = function(){

    var GameClosure = function() {

        var canv = document.getElementById("canv");
        var canvContext = canv.getContext("2d");

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

        var tile = new Image();
        tile.src = "tile.png"

        function loadSprite(){
            sprite.onload = function(){
                canvContext.drawImage(sprite, 50, 50);
                };
        }

        function loadTiles(){
            tile.onload = function(){
                for(var i = 0; i < 800; i += 16){
                    for(var r = 0; r < 608; r += 16){
                        canvContext.drawImage(tile, i, r);
                    }
                }
            };
        }

        return{
            loadTiles: loadTiles,
            loadSprite: loadSprite
            };

    }();

    GameClosure.loadTiles();
    GameClosure.loadSprite();

}

I am getting an odd problem with this. When I load it up, the majority of the time, only the tiles will load up. I've tried a couple of things so far, I've switched the GameClosure.loadTiles() and GameClosure.loadSprite(); calls to see if the load order made any difference. It doesn't. I even tried creating a second context and assigning the tiles to one and the sprite to another, but this made no difference. Commenting out the tile call produces the sprite correctly.

It gets even odder. I was refreshing the page rapidly and I noticed that occasionally (with no pattern to it, sometime it could happen 3 times in a row, other time once in 20) the tiles would load AND the sprite would load on top as I would expect it to.

Can this be fixed? My only guess is that my code is running somewhat asyncronously and the for loops creating the tiles are completing after the sprite has been loaded, but looking at my code I don't see where this could be happening.

Upvotes: 0

Views: 245

Answers (2)

Philipp
Philipp

Reputation: 69663

When you set an onload handler, your javascript will continue while the resource loads in the background. The handler will be executed when the resource has loaded. You have no way to tell when that will happen and in what order.

When you have multiple resources and want to call your draw-function the moment the last one has loaded, you could have a global preloader-object. Each onload-handler should call a function on the preloader to inform it that the resource has loaded. That function should check if all resources have reported in, and when that's the case execute the draw-function.

Also, when you set an onload-handler and the resource is already loaded. When you set .src and the resource is in the browsers cache, it will get loaded instantly. So you always need to first set .onload and then set .src.

Upvotes: 1

GameAlchemist
GameAlchemist

Reputation: 19294

Separate the concerns. Wait for all resources to be loaded (and the document), then launch your game. Always be sure to hook event handler before assigning src to avoid 'random' (cache-related, in fact) behaviors.

Upvotes: 2

Related Questions