Fadi Bunni
Fadi Bunni

Reputation: 13

javascript: Image drawing(background) on canvas

So the problem that I have is that i can not draw the background first then draw everything else on top of the background. In some places in my code(in the loop function) it works, but in my initialize function it does not. A bit introduction to my code first:

code for getting the background img and drawing it:

function imgImport(imgName,ctx){
    var img = new Image();
    img.onload = function(){
        ctx.drawImage(img,0,0);
    };
    img.src = 'client/img/' + imgName + '.jpg';
}

module.exports = imgImport;

cool, now in my initialize function i use the above code like this:

// var img = new Image();
// img.src = 'client/img/spaceship.jpg';
// ctx.drawImage(img,0,0);
Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);

Dont mind the 3 out commented lines for now. The first active line Img('spaceship', ctx): is the above imgImport function being used through nodejs. The DrawGrayzonePlanets can be seen below:

function drawGrayzonePlanets(ctx,serverObjects){
  for(object in serverObjects){
    obj = serverObjects[object];
    Drawobjects(ctx,obj);
  }
}

Essentially the function above gets data from the server and uses Drawobjects() function to draw the planets, looking like this:

function drawObjects(ctx,status){
    switch(status.shape){
      case "circle":
        var status = status.cic;
        console.log(status);
        ctx.fillStyle = status.color;
        ctx.beginPath();
        ctx.arc(status.x,status.y,status.planetSize,0,2*Math.PI);
        ctx.stroke();
        ctx.fill();
        break;
    }
}

module.exports = drawObjects;

now if i run the Img() function first then drawGrayzonePlanets() function after, the planets will be drawn behind the background, meaning they can not be seen. same happens if I change the order of the code, which is obvious. Now I found a way to solve this problem by uncommenting the 3 lines and outcommenting the img() function. and keep the drawGrayzonePlanets() function. like so:

var img = new Image();
img.src = 'client/img/spaceship.jpg';
ctx.drawImage(img,0,0);
//Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);

The above code works, the planets will be drawn on the background. But I just don't understand why that method works and not just by using the Img() function only. It might have to do with the img.onload = function(){} maybe, but i can't see why?

Can someone explain what is actually happening?

Upvotes: 1

Views: 1906

Answers (2)

Jonas Wilms
Jonas Wilms

Reputation: 138257

In your first code youre awaiting the background to finish loading, then draw it. This is obviosly later than the drawing of the other images. In your second code youre not awaiting the loading. The best solution would be a callback:

function imgImport(imgName,ctx,callback){
  var img = new Image();
  img.onload = function(){
    ctx.drawImage(img,0,0);
    callback();
   };
   img.src = 'client/img/' + imgName + '.jpg';
}

Than use like this:

 Img('spaceship',ctx,function(){
   alert("bckground loading finished. Continue loading...");
   drawGrayzonePlanets(ctx,serverObjects);
});

Upvotes: 1

Matis Lepik
Matis Lepik

Reputation: 1152

Because your imgImport is an asynchronous function. The code inside of img.onload gets run after the image has loaded - but while the image is still loading, the rest of your code gets run, drawing the planets. Then, after a while, the image arrives and draws it ontop.

You could, for example, give the imgImport function a third callback argument and run the rest of your code there:

function imgImport(imgName,ctx,callback){
    var img = new Image();
    img.onload = function(){
        ctx.drawImage(img,0,0);
        callback()
    };
    img.src = 'client/img/' + imgName + '.jpg';
}

And execute it like this:

Img('spaceship',ctx,function() {
    drawGrayzonePlanets(ctx,serverObjects);
});

Upvotes: 0

Related Questions