javascript:画布上的图像绘制(背景)

javascript:画布上的图像绘制(背景),javascript,node.js,canvas,drawing,Javascript,Node.js,Canvas,Drawing,所以我的问题是,我不能先画背景,然后再在背景上画其他所有东西。在我的代码中的某些地方(在循环函数中),它可以工作,但在初始化函数中它不能工作。首先介绍一下我的代码: 获取背景img并绘制它的代码: function imgImport(imgName,ctx){ var img = new Image(); img.onload = function(){ ctx.drawImage(img,0,0); }; img.src = 'client/i

所以我的问题是,我不能先画背景,然后再在背景上画其他所有东西。在我的代码中的某些地方(在循环函数中),它可以工作,但在初始化函数中它不能工作。首先介绍一下我的代码:

获取背景img并绘制它的代码:

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;
酷,现在在我的初始化函数中,我使用上面的代码如下:

// var img = new Image();
// img.src = 'client/img/spaceship.jpg';
// ctx.drawImage(img,0,0);
Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);
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;
Img('spaceship',ctx,function() {
    drawGrayzonePlanets(ctx,serverObjects);
});
 Img('spaceship',ctx,function(){
   alert("bckground loading finished. Continue loading...");
   drawGrayzonePlanets(ctx,serverObjects);
});
现在不要介意这三行评论。第一条活动线Img(“太空船”,ctx):是通过NodeJ使用的上述imgImport功能。下面可以看到DrawGrayZonePlanet:

function drawGrayzonePlanets(ctx,serverObjects){
  for(object in serverObjects){
    obj = serverObjects[object];
    Drawobjects(ctx,obj);
  }
}
本质上,上述函数从服务器获取数据,并使用Drawobjects()函数绘制行星,如下所示:

// var img = new Image();
// img.src = 'client/img/spaceship.jpg';
// ctx.drawImage(img,0,0);
Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);
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;
Img('spaceship',ctx,function() {
    drawGrayzonePlanets(ctx,serverObjects);
});
 Img('spaceship',ctx,function(){
   alert("bckground loading finished. Continue loading...");
   drawGrayzonePlanets(ctx,serverObjects);
});
现在,如果我先运行Img()函数,然后再运行drawGrayzonePlanets()函数,行星将被画在背景后面,这意味着它们无法被看到。如果我改变代码的顺序也会发生同样的情况,这是显而易见的。现在我找到了一种解决这个问题的方法,取消对这3行的注释,并对img()函数进行注释。并保留drawGrayzonePlanets()函数。像这样:

var img = new Image();
img.src = 'client/img/spaceship.jpg';
ctx.drawImage(img,0,0);
//Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);
上面的代码工作,行星将被画在背景上。但是我不明白为什么这个方法是有效的,而不仅仅是通过使用Img()函数。这可能与img.onload=function(){}有关,但我不明白为什么


有人能解释一下到底发生了什么吗

因为imgImport是一个异步函数。图像加载后,
img.onload
中的代码将运行,但当图像仍在加载时,其余代码将运行,绘制行星。然后,过了一会儿,图像到达并将其绘制到顶部

例如,您可以为imgImport函数提供第三个回调参数,并在其中运行其余代码:

function imgImport(imgName,ctx,callback){
    var img = new Image();
    img.onload = function(){
        ctx.drawImage(img,0,0);
        callback()
    };
    img.src = 'client/img/' + imgName + '.jpg';
}
然后像这样执行它:

// var img = new Image();
// img.src = 'client/img/spaceship.jpg';
// ctx.drawImage(img,0,0);
Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);
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;
Img('spaceship',ctx,function() {
    drawGrayzonePlanets(ctx,serverObjects);
});
 Img('spaceship',ctx,function(){
   alert("bckground loading finished. Continue loading...");
   drawGrayzonePlanets(ctx,serverObjects);
});

在您的第一个代码中,您正在等待后台完成加载,然后绘制它。这显然比其他图像的绘制要晚。在第二个代码中,您没有等待加载。最好的解决方案是回调:

function imgImport(imgName,ctx,callback){
  var img = new Image();
  img.onload = function(){
    ctx.drawImage(img,0,0);
    callback();
   };
   img.src = 'client/img/' + imgName + '.jpg';
}
而不是像这样使用:

// var img = new Image();
// img.src = 'client/img/spaceship.jpg';
// ctx.drawImage(img,0,0);
Img('spaceship',ctx);
drawGrayzonePlanets(ctx,serverObjects);
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;
Img('spaceship',ctx,function() {
    drawGrayzonePlanets(ctx,serverObjects);
});
 Img('spaceship',ctx,function(){
   alert("bckground loading finished. Continue loading...");
   drawGrayzonePlanets(ctx,serverObjects);
});

我没有看到在任何地方定义了
Img
函数。你能把代码剪成snipper或JSFIDLE吗?