javascript холст рисование изображения

Я пытаюсь нарисовать несколько изображений на холсте. У меня проблема, потому что иногда все изображения нарисованы, а иногда некоторые отсутствуют. Пробую на хроме и фаерфоксе.

Есть код:

 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"), результат тот же.


person Lilice    schedule 23.06.2016    source источник
comment
Проверить .onerror событие...   -  person Rayon    schedule 23.06.2016
comment
Это проблема закрытия. Некоторые предложения здесь: stackoverflow.com/questions/17578280/   -  person    schedule 23.06.2016


Ответы (1)


Это проблема закрытия. Поскольку загрузка изображения является асинхронной, значения, которые все еще ссылаются на родительскую область внутри обработчика, больше не содержат значений, которые вы ожидаете от них.

Для этого вам понадобится способ удерживать это значение до тех пор, пока изображение не загрузится должным образом. Вы можете использовать закрытие или как здесь привязку -

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>

Также см. эту тему для других подходов.

Ресурсы:

person Community    schedule 23.06.2016
comment
Спасибо, это работа! Вы знаете, где я могу найти информацию о замыканиях? - person Lilice; 23.06.2016
comment
@alin не проблема! Дополнительную информацию о замыканиях можно найти здесь: developer.mozilla.org/en -US/docs/Web/JavaScript/Closures - person ; 23.06.2016
comment
@alind и bind() (используется здесь как решение): developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/ - person ; 23.06.2016