javascript canvas 绘制图像
javascript canvas drawimage
我尝试在 canvas 中绘制多个图像。我有一个问题,因为有时会绘制所有图像,有时会丢失一些图像。我试试 chrome 和 firefox。
有代码:
for (i=0; i<tileList.length; i++)
{
// var img_src = new Image();
var img_src = document.createElement("img");
var c = tileList[i].y ;
var r = tileList[i].x;
img_src.onload = function (){
ctx.drawImage(img_src, r * tileSize, c * tileSize, tileSize * tileList[i].qw, tileSize * tileList[i].qh);
}
img_src.src = './viewer/images/'+path+'/LOD'+glod+'/tiles_'+ c + '_' + r +'.jpeg';
new Image()
和document.createElement("img")
我都试了,结果一样
这是一个闭包问题。由于图像加载是异步的,因此仍然从处理程序内部引用父范围的值不再包含您希望它们持有的值。
为此,您需要一种方法来保留这些值,直到图像正确加载。您可以使用闭包,或者像这里那样绑定 -
function handler() {
var i = this.i;
ctx.drawImage(this.img_src,
this.r * tileSize,
this.c * tileSize,
tileSize * tileList[i].qw, tileSize * tileList[i].qh);
}
注意它需要一个对象引用。在循环中我们现在可以做:
for (var i = 0; i < tileList.length; i++) {
var o = {
img_src: new Image,
c: tileList[i].y,
r: tileList[i].x,
i: i
};
o.img_src.onload = handler.bind(o); // bind this object (o)
o.img_src.src = './viewer/images/'+path+'/LOD'+glod+'/tiles_'+ c + '_' + r +'.jpeg';
}
所以我们在循环中创建了一个新的对象实例。我们存储以后需要的数据。然后我们设置处理程序但绑定到对象,该对象将把它保存在内存中,直到我们不再引用它。绑定它还允许我们使用 this
来引用我们为处理程序创建的原始对象。
这是一种干净的方法,不需要匿名函数,也不会妨碍图像对象本身。
概念代码示例
// conceptual example
var ctx = c.getContext("2d"),
list = [ // pseudo list serving this example
{x:2, y:5, src: "//i.imgur.com/kPX1264b.jpg"},
{x: 160, y:7, src: "//i.imgur.com/IgPTywZb.jpg"}
];
function handler() {
console.log(this.i, this.r, this.c, this.img_src.src);
ctx.drawImage(this.img_src, this.r, this.c);
}
for (i=0; i < list.length; i++) {
var o = {
img_src: new Image,
c: list[i].y,
r: list[i].x,
i: i
};
o.img_src.onload = handler.bind(o); // bind this object (o)
o.img_src.src = list[i].src;
}
<canvas id=c></canvas>
另请参阅 this thread 了解其他方法。
资源:
我尝试在 canvas 中绘制多个图像。我有一个问题,因为有时会绘制所有图像,有时会丢失一些图像。我试试 chrome 和 firefox。
有代码:
for (i=0; i<tileList.length; i++)
{
// var img_src = new Image();
var img_src = document.createElement("img");
var c = tileList[i].y ;
var r = tileList[i].x;
img_src.onload = function (){
ctx.drawImage(img_src, r * tileSize, c * tileSize, tileSize * tileList[i].qw, tileSize * tileList[i].qh);
}
img_src.src = './viewer/images/'+path+'/LOD'+glod+'/tiles_'+ c + '_' + r +'.jpeg';
new Image()
和document.createElement("img")
我都试了,结果一样
这是一个闭包问题。由于图像加载是异步的,因此仍然从处理程序内部引用父范围的值不再包含您希望它们持有的值。
为此,您需要一种方法来保留这些值,直到图像正确加载。您可以使用闭包,或者像这里那样绑定 -
function handler() {
var i = this.i;
ctx.drawImage(this.img_src,
this.r * tileSize,
this.c * tileSize,
tileSize * tileList[i].qw, tileSize * tileList[i].qh);
}
注意它需要一个对象引用。在循环中我们现在可以做:
for (var i = 0; i < tileList.length; i++) {
var o = {
img_src: new Image,
c: tileList[i].y,
r: tileList[i].x,
i: i
};
o.img_src.onload = handler.bind(o); // bind this object (o)
o.img_src.src = './viewer/images/'+path+'/LOD'+glod+'/tiles_'+ c + '_' + r +'.jpeg';
}
所以我们在循环中创建了一个新的对象实例。我们存储以后需要的数据。然后我们设置处理程序但绑定到对象,该对象将把它保存在内存中,直到我们不再引用它。绑定它还允许我们使用 this
来引用我们为处理程序创建的原始对象。
这是一种干净的方法,不需要匿名函数,也不会妨碍图像对象本身。
概念代码示例
// conceptual example
var ctx = c.getContext("2d"),
list = [ // pseudo list serving this example
{x:2, y:5, src: "//i.imgur.com/kPX1264b.jpg"},
{x: 160, y:7, src: "//i.imgur.com/IgPTywZb.jpg"}
];
function handler() {
console.log(this.i, this.r, this.c, this.img_src.src);
ctx.drawImage(this.img_src, this.r, this.c);
}
for (i=0; i < list.length; i++) {
var o = {
img_src: new Image,
c: list[i].y,
r: list[i].x,
i: i
};
o.img_src.onload = handler.bind(o); // bind this object (o)
o.img_src.src = list[i].src;
}
<canvas id=c></canvas>
另请参阅 this thread 了解其他方法。