简体   繁体   中英

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?

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);
});

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);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM