1
var c=document.getElementById("cvs");
var ctx=c.getContext("2d");
var imgArray = [];          
for (var i=0;i<data.length;i++){
    var drawRepeat = Math.floor((data[i]/divider)); 
    imgArray[i] = [];   
    for (var j=0;j<drawRepeat;j++){
            //alert(j);
        var xPos = ((i*30)+10);
        var yPos = 250-((j*30)+30);
        imgArray[i][j] = new Image();
        imgArray[i][j].src="assets/orange.png";
        imgArray[i][j].onload = function(){
        ctx.drawImage(imgArray[i][j],xPos,yPos);
        };

    }
}

我想用 for 循环绘制多个图像。奇怪的是,当我在 for 循环中放置一个 alert() 时它可以工作吗?但如果我将其注释掉,它只会显示图像中的 1 个。

有什么解决办法吗?

4

3 回答 3

3

这就是与闭包有关的问题。给出代码后我会解释。

var c = document.getElementById("cvs");
var ctx = c.getContext("2d");
var imgArray = [];
for (var i = 0; i < data.length; i++) {
    var drawRepeat = Math.floor((data[i] / divider));
    imgArray[i] = [];
    for (var j = 0; j < drawRepeat; j++) {
        //alert(j);
        (function (_i, _j) {
            var xPos = ((_i * 30) + 10);
            var yPos = 250 - ((_j * 30) + 30);
            imgArray[_i][_j] = new Image();
            imgArray[_i][_j].src = "assets/orange.png";
            imgArray[_i][_j].onload = function () {
                ctx.drawImage(imgArray[_i][_j], xPos, yPos);
            };
        })(i, j);
    }
}

更新

我做这些奇怪的事情的原因是注册到onload事件的函数将被异步调用 - 即循环将继续并且函数将在图像加载时被调用,而不是在那个时刻。所以会发生什么是这个循环继续,一旦它完成(注意这甚至可能在完成之前发生),i的值将是data.length - 1. 现在,加载了一些图像,然后调用该函数。这个函数指的是i(在你给出的代码中),它现在是data.length - 1. 因此,只有最后一个图像被绘制。我知道这很令人困惑——即使当我第一次偶然发现闭包时我也感到很困惑。我建议你阅读一些关于它们的好文章,你会看到问题所在。

我们所做的是通过创建一个匿名函数来创建一个作用域i(专家可能会发现这个表达式有问题),该函数会立即被调用,并将其值j作为参数传递 -_i并且_j(请注意,我们可以使用相同的名称,但为避免混淆,我没有使用相同的名称)。现在,这些是函数本地的,不会改变。因此,当i加载图像时,它的 onload 函数被调用,该函数_i在数组中绘制图像。

我没有很好地解释它,所以正如我所说,请阅读一些关于闭包的文章。

于 2012-06-06T15:15:27.013 回答
0

预加载图像,而不是使用 onload 处理程序。

于 2012-06-06T15:05:38.723 回答
0
var c=document.getElementById("cvs");
        var ctx=c.getContext("2d");
        var img = new Image();
        img.src="assets/orange.png";
        img.onload = function(){
            for (var i=0;i<data.length;i++){
                var drawRepeat = Math.floor((data[i]/divider));
                for (var j=0;j<drawRepeat;j++){
                    //alert(j);
                    var xPos = ((i*30)+10);
                    var yPos = 250-((j*30)+30);
                    ctx.drawImage(img,xPos,yPos);
                }
            }
        }

我设法解决了 onload 的问题,方法是将 onload 放在 for 循环之外,并将 drawImage 命令放在 onload 函数和 for 循环中。也可以。

于 2012-06-06T16:08:11.157 回答