【问题标题】:drawImage in JavaScript (Canvas)JavaScript中的drawImage(画布)
【发布时间】:2013-12-22 21:44:36
【问题描述】:

我有一个图像对象数组,其中包含所有必要的信息,如路径、x、y、w、h。现在我想在画布上循环绘制所有这些图像.. 但是当我这样做时,它只绘制第一张图像。代码如下:

for(var i=0; i<shapes.length; i++)
{
    var A = shapes.pop();
    if(A.name == 'image' && A.pageNum == pNum)
    {
        var img = new Image();
        img.src = A.path;
        img.onload = function() {
            context.drawImage(img, A.x, A.y, A.w, A.h); 
        }
    }
}

我检查了形状数组中的所有信息...在 if 条件内,在调用 drawImage 函数之前,每个图像的所有信息都是正确的,但是由于某些奇怪的原因,它不显示图像,除了“最后一个”数组(最后弹出的那个)

【问题讨论】:

  • 会不会是所有的图像都在彼此重叠?您正在将所有图像添加到同一个画布中。你检查过每张图片的 x 和 y 值吗?
  • 是的,每张图片的 x 和 ys 都不一样...

标签: javascript canvas html5-canvas drawimage


【解决方案1】:

我不明白您为什么要使用 pop() 来获取对象数据。您可以改为使用 shape[i] 表示法访问每个对象,并且作为奖励,在每个对象中存储图像句柄:

for(var i=0; i<shapes.length; i++)
{
    if(shapes[i].name == 'image' && shapes[i].pageNum == pNum)
    {
        shapes[i].img = new Image();
        shapes[i].img.src = shapes[i].path;
        shapes[i].img.onload = function() {
            context.drawImage(shapes[i].img, shapes[i].x, shapes[i].y, shapes[i].w, shapes[i].h); 
        }
    }
}

【讨论】:

  • 是的,这很有用,但这不是问题……如果有 3 张图像,循环将运行 3 次,并且只会显示一张图像。这就是问题所在..
  • 是的.. 但有什么办法可以解决这个问题?
  • 这里的重点不是优化代码。它是关于让它以某种方式显示所有图像。我没有看到上面的代码与最初的代码有任何不同...
【解决方案2】:

您的图片加载代码有问题。

每张图片都需要一些时间来加载,然后你已经用另一个 new Image() 覆盖了 var img;

这是一个图像加载器的示例,它仅在所有图像都已加载并准备好绘制后执行:

[ 警告:未经测试的代码——可能需要进行一些调整! ]

// image loader

var imageURLs=[];  // put the paths to your images in this array
var imagesOK=0;
var imgs=[];
imageURLs.push("");
loadAllImages(start);

function loadAllImages(callback){
    for (var i=0; i<imageURLs.length; i++) {
        var img = new Image();
        imgs.push(img);
        img.onload = function(){ 
            imagesOK++; 
            if (imagesOK>=imageURLs.length ) {
                callback();
            }
        };
        img.onerror=function(){alert("image load failed");} 
        img.crossOrigin="anonymous";
        img.src = imageURLs[i];

        // note: instead of this last line, you can probably use img.src=shapes[i].path;
    }      
}

function start(){

    // the imgs[] array holds fully loaded images
    // the imgs[] are in the same order as imageURLs[]

    for(var i=0;i<shapes.length;i++){
        var shape=shapes[i];
        context.drawImage(imgs[i],shape.x,shape.y,shape.w,shape.h);
    }

}

【讨论】:

  • 是的..这似乎是问题所在。您对如何在图像完成加载之前让循环等待有什么建议吗?
  • 感谢您指引我朝着正确的方向前进……我终于成功了。这很容易:)(已发布答案)
【解决方案3】:

这是某种闭包的问题...例如,在加载图像之前完成循环之类的。对我有用的解决方案是将所有图像加载代码放在一个单独的函数中并从循环中调用该函数:

if(A.name == 'image' && A.pageNum == pNum)
{
    displayImage(A.path, A.x, A.y, A.w, A.h);

}
function displayImage(path, x, y, w, h)
{
    var img = new Image();
    img.src = path;

    img.onload = function() {
        context.drawImage(img, x, y, w, h);
    }
}

【讨论】:

  • 也许你可以考虑给 markE 一些荣誉,因为他通过支持/接受他的回答来引导你找到你找到的解决方案。也看看我的YAIL 图像加载器。 :-)
猜你喜欢
  • 1970-01-01
  • 2011-05-10
  • 2021-08-06
  • 1970-01-01
  • 2012-11-30
  • 1970-01-01
  • 1970-01-01
  • 2015-03-02
  • 2012-08-28
相关资源
最近更新 更多