【问题标题】:draw image on canvas after load into array加载到数组后在画布上绘制图像
【发布时间】:2014-04-10 09:31:17
【问题描述】:

我尝试在加载每个图像后创建要在画布上显示的图像数组。没有错误,没有平局……

    var x=...
var y=...
var canvas = document.getElementById(sCanvasName);
var context = canvas.getContext('2d');

var imageCardObj = [];

//vCards contains the images file names
for (var k=0;k<vCards.length;k++){
    imageCardObj[k] = new Image();

    var func = function(){
            var c = arguments[3];
            try{                
                c.drawImage(arguments[0], arguments[1], arguments[2]);
            }catch(e){
                alert(e.message)
            }
        }

        imageCardObj[k].onload = func(imageCardObj[k], x, y, context);

        imageCardObj[k].src = "res/img/"+vCards[k].trim()+".png";   

        x+=40;
    }

【问题讨论】:

  • 这段代码是否在window.onload-function 中? document.getElementById() 可能没有返回画布元素。
  • 不,代码在链接调用的函数中。画布没问题 - 我试图在循环外绘制一个 img 并且它有效
  • 好的。我看到您创建了一个名为 func 的函数,但我没有看到您曾经调用过它。
  • 这里:imageCardObj[k].onload = func(imageCardObj[k], x, y, context);

标签: javascript image canvas


【解决方案1】:

您正在调用func() 处理程序并将结果提供给图像的onload 处理程序。这不会很好地工作..你不能以这种方式将参数传递给处理函数。

试试这个:

var func = function(){

    // "this" will be the current image in here

    var c = arguments[3];
    try{                
        c.drawImage(this, x, y); // you need to reference x and y
    }catch(e){
        alert(e.message)
    }
}

imageCardObj[k].onload = func;  // only a reference here

如果您需要不同的 x 和 y,那么您需要在附加数组中维护它们,或者使用对象来嵌入图像,其预期的 x 和 y 并使用 url 来识别有问题的图像func() 回调。

另请注意,加载顺序可能会有所不同,因为最后加载的图像可能在第一个之前完成,因此当您绘制图像时,它们可能不会以相同的顺序出现。

您可能想要这样做:

var files = [url1, url2, url, ...],
    images = [],
    numOfFiles = files.length,
    count = numOfFiles;

// function to load all images in one go
function loadImages() {

    // go through array of file names
    for(var i = 0; i < numOfFiles; i++) {

        // create an image element
        var img = document.createElement('img');

        // use common loader as we need to count files
        img.onload = imageLoaded;
        //img.onerror = ... handle errors too ...
        //img.onabort = ... handle errors too ...

        img.src = files[i];

        // push image onto array in the same order as file names
        images.push(img);
    }
}
function imageLoaded(e) {

    // for each successful load we count down
    count--;
    if (count === 0) draw(); //start when all images are loaded
}

然后您可以在加载图像后开始绘图 - 图像现在与原始数组的顺序相同:

function draw() {
    for(var i = 0, img; img = images[i++];)
        ctx.drawImage(img, x, y); // or get x and y from an array
}

希望这会有所帮助!

【讨论】:

  • 感谢肯,很好的解决方案和解释!我不在乎图像的加载顺序 - 它们非常小,可能它们会同时加载。只有一个问题:func() 中的 X 和 Y 是全局变量吗?
  • @Vincent 没问题! X 和 y 是全局的或至少在父范围内(仅作为示例)。它们可以来自数组或对象(带有图像、url 等的对象,因此您可以使用 f.ex. url 来识别图像)。
  • 我对每个 img 的 X 和 Y 的增量有一些问题,将它们视为全局变量。我通过将 X 分配给 img obj 来解决: imageCardObj[k].xxx=x;并在 func context.drawImage(this, this.xxx, yStreet); 中使用 xxx;
【解决方案2】:

这是最终(工作)版本

var x=...
var y=...
var canvas = document.getElementById(sCanvasName);
var context = canvas.getContext('2d');
var imageCardObj = [];

    for (var k=0;k<vCards.length;k++){

        imageCardObj[k] = new Image();
         imageCardObj[k].xxx=x;

        var func = function(){              

            try{                
                context.drawImage(this, this.xxx, yStreet);                 
            }catch(e){
                alert(e.message)
            }
        }

        imageCardObj[k].onload = func;      
        imageCardObj[k].src = 'res/img/'+vCards[k].trim()+".png";   
        x +=40;         

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 2023-04-02
    • 2018-12-09
    相关资源
    最近更新 更多