简体   繁体   English

JavaScript的画布drawimage

[英]javascript canvas drawimage

I try to draw several images in a canvas. 我尝试在画布上绘制几个图像。 I have an issue because sometimes all the images are drawn and sometimes several are missing. 我有一个问题,因为有时会绘制所有图像,有时会丢失一些图像。 I try on chrome and firefox. 我尝试使用Chrome和Firefox。

There is the code: 有代码:

 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';

I try both new Image() and document.createElement("img") , the result is the same. 我尝试了new Image()document.createElement("img") ,结果都是一样的。

This is a closure problem. 这是一个关闭问题。 As the image loading is asynchronous the values, still referenced to the parent scope from inside the handler, does no longer contain the values you'd expect them to hold. 由于图像加载是异步的,因此仍从处理程序内部引用到父作用域的值不再包含您希望它们保存的值。

For this you would need a way to hold on to those value until the image has properly loaded. 为此,您需要一种方法来保持这些值,直到图像正确加载为止。 You could use closure, or as here binding - 您可以使用闭包,也可以使用此处的绑定-

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);
}

Notice it takes an object reference. 注意,它带有一个对象引用。 Inside the loop we can now do: 在循环内部,我们现在可以执行以下操作:

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';
}

So we create a new object instance inside the loop. 因此,我们在循环内创建了一个新的对象实例。 We store the data we need for later. 我们存储以后需要的数据。 Then we set the handler but bound to the object which will keep it in memory until we no longer reference it. 然后,我们设置处理程序,但绑定到该对象,该对象将使其保留在内存中,直到不再引用它为止。 Binding it also allows us to use this to reference the original object we created for the handler. 绑定它还允许我们使用this来引用我们为处理程序创建的原始对象。

This is a clean approach, does not need anonymous functions and does not hamper the image object itself. 这是一种干净的方法,不需要匿名函数并且不会妨碍图像对象本身。

Conceptual code example 概念代码示例

 // 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> 

Also see this thread for other approaches. 另请参见此线程以了解其他方法。

Resources: 资源:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM