Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/422.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将图像加载到多个画布时出现问题_Javascript_Html_Canvas - Fatal编程技术网

Javascript 将图像加载到多个画布时出现问题

Javascript 将图像加载到多个画布时出现问题,javascript,html,canvas,Javascript,Html,Canvas,我有一个模拟平铺图像的画布元素表。我只需要填充视口中当前可见的平铺。这是我使用的代码 for (var ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) { for (var iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) { var canvasDispJq = $("canvas#" + frameResId

我有一个模拟平铺图像的画布元素表。我只需要填充视口中当前可见的平铺。这是我使用的代码

for (var ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
        for (var iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
            var canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "-    disp");
            var canvasDisp = canvasDispJq.get(0);
            var image = new Image();
            var context = canvasDisp.getContext("2d");
            image.onload = function() {
                context.drawImage(image, 0, 0);
            }
            image.src = self.baseURL + '/' + canvasDispJq.attr("id");
        }
    }
};
for(var ix=visibleRange.firstX;ix 0&&
(canvasDispJq.position().top+imagePosition.y)
可见范围计算方式的差异应该无关紧要,因为我在Firebug中进行了检查,两种方法都正确选择了要渲染的平铺,并且从服务器下载了实际的平铺图像,但对于第一种方法,只显示最后一个平铺,而对于第二种方法,所有平铺都正确渲染


提前感谢您的建议。

造成差异的主要原因如下:

var image = new Image();
var context = canvasDisp.getContext("2d");
image.onload = function() {
    context.drawImage(image, 0, 0);
}
这样做的目的是创建一个闭包并将其分配给映像的
load
事件。闭包关闭
上下文
图像
变量(以及其他几个变量)。这里的关键是,它对这些变量有一个持久的引用,而不是创建函数时它们的值的副本。因为上面的代码在一个循环中,所以创建的所有函数(闭包)都将引用相同的
上下文
图像
——循环创建的最后一个函数

每个
版本中都不会发生这种情况,因为在该版本中,闭包会关闭一个不变的变量,即通过调用传递给
每个
的迭代器函数创建的
上下文
图像

有关闭包的更多信息,请参见:

也许有点离题,也许没有:如果您的
var
s位于不同的位置,这可能会更清楚。特别是,它与其他语言(例如,C,C++,java,C等)中的变量声明不一样,部分是因为JavaScript没有块级范围(仅函数级范围和全局范围)。 以下是JavaScript解释器如何查看您的第一个版本:

var ix, iy, canvasDispJq, canvasDisp, image, context;
for (ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
        for (iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
            canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "-    disp");
            canvasDisp = canvasDispJq.get(0);
            image = new Image();
            context = canvasDisp.getContext("2d");
            image.onload = function() {
                context.drawImage(image, 0, 0);
            };
            image.src = self.baseURL + '/' + canvasDispJq.attr("id");
        }
    }
}

现在,由
createOnloadHandler
函数创建的闭包将关闭
ct
img
,而不是
context
image
。每个闭包都有自己的副本(传递到创建该闭包的
createOnloadHandler
调用中的副本)。

非常感谢!真的吗helped@Maksym:很好,不用担心。顺便说一下,我读了你关于闭包的博文。这真的让我明白了。再次感谢!
var ix, iy, canvasDispJq, canvasDisp, image, context;
for (ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
        for (iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
            canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "-    disp");
            canvasDisp = canvasDispJq.get(0);
            image = new Image();
            context = canvasDisp.getContext("2d");
            image.onload = function() {
                context.drawImage(image, 0, 0);
            };
            image.src = self.baseURL + '/' + canvasDispJq.attr("id");
        }
    }
}
var ix, iy, canvasDispJq, canvasDisp, image, context;
for (ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
        for (iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
            canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "-    disp");
            canvasDisp = canvasDispJq.get(0);
            image = new Image();
            context = canvasDisp.getContext("2d");
            image.onload = createOnloadHandler(context);
            image.src = self.baseURL + '/' + canvasDispJq.attr("id");
        }
    }
}

function createOnloadHandler(ct, img) {

    return function() {
        context.drawImage(img, 0, 0);
    };
}