我可以将数组值插入到画布的图像绘制函数中吗?
Can I plug in array values into a image drawing function of the canvas?
我想创建一行相同的图片,像这样:https://i.stack.imgur.com/XrWl7.jpg
每个草的图片是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)
}
但由于某种原因,它根本不起作用。它不会创建一个单一的图像。是否可能是因为参数不允许从数组中"获取"值?还是我做错了什么?
您必须给您的草图像加载时间。
您可以使用图像对象上的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.
你犯了一个"闭包错误"。
综上所述,当你创建一个函数对象(在这个例子中是你的事件回调)时,它会"记住"它的上下文(在这个例子中是变量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
为假。当它停止时,i
已经增加到25。
当你的回调被执行时,i
仍然是25。
EventListener
s,并使用回调函数分别绘制一个图像。我还没有测试性能,但一个更简单的事情是注册一个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);
}
将函数用圆括号括起来,并在圆括号之间传递参数,就像调用普通函数一样。
- 画布:逐像素绘制图像并请求动画帧计时
- WebGL绘制图像
- 多重绘制图像后画布清除
- 可以'清除Rect后,不要在画布上绘制图像
- 如何在单页应用程序中重新绘制图像
- 画布中的图像在绘制图像后立即消失
- 使用Canvas绘制图像
- 如何在javascript中在图像上绘制图像(没有CSS和HTML)
- 使用模式在 HTML5/JS 中绘制图像
- 绘制并重新绘制图像以模拟动画是行不通的
- Dart Canvas未绘制图像
- 在新窗口中打开时,未在画布中绘制图像
- 在画布上绘制图像并导出打印质量的图像
- 用一个加载项绘制图像阵列
- html画布绘制图像不起作用
- Chrome 31.0 HTML5画布绘制图像
- 用HTML5和Javascript绘制图像
- 在新框架上绘制图像,同时仍然使用P5.js中的利萨茹曲线
- 如何在画布上更快地绘制图像
- 在 HTML5 画布中绘制图像,同时保留图像