我想像这样创建一行相同的图片: http://imgur.com/4ylymJz
每张草图片的面积为70x70像素。我想使用for循环和存储25个值的数组来创建它。这就是代码:
var pic = new Image()
var picture = pic.src = "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSXEODf7WhGahJl_eRIh5Np063DS1MtQhjem1NDJLfdFB2am4YB";
var grassXs = [];
for (var i = 0; i < 25; i++) {
grassXs.push(i*70);
}
for (var i = 0; i < grassXs.length;i++) {
pic.addEventListener("load", function () {
board.drawImage(pic,grassXs[i],430,70,70)
}, false)
}
但由于某种原因,它完全没有工作。它不会创建单个图像。可能是因为参数不允许&#34;采取&#34;数组中的值?或者这只是我做错了什么?
答案 0 :(得分:0)
你必须给草图像加载时间。
您可以使用图像对象上的onload
回调来执行此操作。
快速举例:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var count=25;
var width=70;
var img=new Image();
img.onload=start;
img.src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSXEODf7WhGahJl_eRIh5Np063DS1MtQhjem1NDJLfdFB2am4YB";
function start(){
canvas.width=width*count;
canvas.height=img.height;
for(var i=0;i<count;i++){
ctx.drawImage(img,i*width,0,width,img.height);
}
}
<canvas id="canvas" width=300 height=300></canvas>
[有关您的代码的其他说明]
例如,您的代码将按以下顺序执行:
// a new image object is created
var pic = new Image()
// "pic" BEGINS to load, but is not yet fully loaded
// and is not yet ready to draw
var picture = pic.src = "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSXEODf7WhGahJl_eRIh5Np063DS1MtQhjem1NDJLfdFB2am4YB";
// This code is immediately executed even though
// "pic" has not yet fully loaded
var grassXs = [];
// This entire loop is immediately executed even though
// "pic" has not yet fully loaded
for (var i = 0; i < 25; i++) {
grassXs.push(i*70);
}
// This entire loop is immediately executed even though
// "pic" has not yet fully loaded
// Since "pic" is not fully loaded each "drawImage" below is
// drawing empty images onto the canvas
for (var i = 0; i < grassXs.length;i++) {
// pic is being given 25 event handlers which all point
// to the final value of "i". Since grassXs[25] is undefined
// all of the drawImages are ineffective
pic.addEventListener("load", function () {
board.drawImage(pic,grassXs[i],430,70,70)
}, false)
}
// about this time (or later if the "pic" is a large image)
// "pic" is fully loaded and is now ready to drawImage with.
// Unfortunately, all the "drawImage"s have been executed with
// invalid grassXs.
答案 1 :(得分:0)
你有一个"closure mistake"
总结上面的链接,当你创建一个函数对象(在这种情况下是你的事件回调)时,它会记住&#34;它的上下文(在本例中是变量i
)而不是直接的值
问题是在循环中,变量i
会发生变化。当调度onload
事件时(在循环结束后),i
的值为25.
因此,board.drawImage(pic,grassXs[25],430,70,70)
(注意25)在加载图像时被调用24次。 grassXs[25]
是undefined
。这就是为什么没有显示的原因。
为什么i
25而不是24?
因为for循环将执行您的代码(并递增i
),直到条件i<24
为false。当它停止时,i
已增加到25.
当你的回调被执行时,i
仍然是25。
解决此问题的最简单方法是纠正代码中的另一个缺陷。你正在做的是你在图像对象上为同一个事件注册了24 EventListener
个,并且每个都有一个回调函数来绘制一个图像。
我没有测试过性能,但更简单的做法是使用一个回调函数注册一个EventListener来绘制24个图像。
pic.addEventListener("load", function () {
for (var i = 0; i < grassXs.length;i++) {
board.drawImage(pic,grassXs[i],430,70,70);
}
}, false)
此外,你的两个for循环具有完全相同的条件(grassXs.length
在你的第一个循环之后是25)所以你可以通过在第二个循环中乘以70来组合它们。以下是完整代码的更正版本:
var pic = new Image()
var picture = pic.src = "https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSXEODf7WhGahJl_eRIh5Np063DS1MtQhjem1NDJLfdFB2am4YB";
var count = 25;
pic.addEventListener("load", function () {
for (var i = 0; i < count;i++) {
board.drawImage(pic,i*70,430,70,70);
}
}, false)
如果您将来遇到另一个关闭问题,那么如果没有更简单的方法,您可以如何纠正这个问题。您应该阅读我上面发布的链接页面,但这是一个代码示例。
您可以决定将代码放在外部函数中,并使用i
作为参数调用此函数:
function setListener(offset)
{
pic.addEventListener("load", function () {
board.drawImage(pic,offset,430,70,70);
}, false) ;
}
for(i = 0; i < 25; i++)
{
setListener(i*70);
}
或者您可以使用自动执行的匿名函数(在您的情况下,我将使用第一种方式,直到您对该语言更有经验。)。
for(i = 0; i < 25; i++)
{
(function(offset) {
pic.addEventListener("load", function () {
board.drawImage(pic, offset,430,70,70);
}, false);
})(i);
}
将函数包装在括号中并在括号之间传递参数,就像调用普通函数一样。