Массив картинок и обработка после их загрузки

135
14 апреля 2018, 20:06

Есть массив картинок, которые отбираю по имени класса. Нужно их ресайзить в зависимости от соотношения ширина/высота. Но т.к. не все картинки загружены, когда выполняется скрипт, то img.width возвращает 0. Пытаюсь добавить обработку картинок после загрузки, но не выходит - все равно возвращает 0. Где проблема?

function img_size() {
  var array = document.getElementsByClassName('mob_img_select');
  console.log(array);
  for (var i = 0; i < array.length; i++) { 
    array[i].onload = onload_img(array[i]);
  }
}
function onload_img(img) {
  console.log(img);
  if (img.width >= img.height) {
    console.log('размер ' + img.width + 'x' + img.height);
    img.className += ' mob_img_width';
  }
  else {
    console.log('размер ' + img.width + 'x' + img.height);
    img.className += ' mob_img_height';
  }
}
img_size()

Соответственно, первые картинок 10 обрабатываются нормально и в консоли вижу

размер 210x210

А остальные выводит

размер 0x0

Если страницу перезагрузить, то все обрабатывается правильно, т.к. картинки уже в кеше.

Answer 1

Проблема №1 в том что Вы присваиваете свойству onload не функцию, а результат ее выполнения.

Проблема №2 в том что пытаясь передать array[i] параметром - не учитываете асинхронность вызова onload_image. На момент выполнения этого обработчика, значение его аргумента img может указывать не на тот элемент, который был в array[i] при установке свойства onload.
Это происходит потому, что цикл for выполняется синхронно и не ожидает завершения обработчика - onload будет вызвана браузером вне общего синхронного потока. Проще говоря, эта функция выполнится именно в момент события load, которое возбудится после полной загрузки изображения.

Для того чтобы код заработал, как Вы ожидаете:

Строку

array[i].onload = onload_img(array[i]);

замените на

array[i].addEventListener('load', onload_img);


Далее, в обработчике onload_img() замените:

  • имя переменной img на this (и уберите аргумент обработчика)
  • имя свойства с height на naturalHeight (если хотите получить высоту изображения, а не высоту элемента)
  • имя свойства width на naturalWidth (соответственно)

document.addEventListener('DOMContentLoaded', img_size);  
setTimeout(console.clear, 1e4);  
 
function img_size() { 
  let array = document.getElementsByClassName('mob_img_select'); 
  for (let i = 0; i < array.length; i++) { 
    array[i].dataset.idx = i;  
    array[i].addEventListener('load', onload_img); 
  } 
} 
 
function onload_img() { 
  let w = this.naturalWidth,  
      h = this.naturalHeight;  
  console.log(`размер изображения ${+this.dataset.idx + 1}: ${w}x${h}`); 
  if (w >= h) 
    this.classList.add('mob_img_width'); 
  else 
    this.classList.add('mob_img_height'); 
}
<img class="mob_img_select" src="https://picsum.photos/400/280/?random"> 
<img class="mob_img_select" src="https://picsum.photos/160/300/?random"> 
<img class="mob_img_select" src="https://picsum.photos/100/65/?random"> 
<img class="mob_img_select" src="https://picsum.photos/200/200/?random"> 
<img class="mob_img_select" src="https://picsum.photos/200/370/?random">

READ ALSO
как убрать соотношения сторон?

как убрать соотношения сторон?

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

175
Проблема с пост-запросом/ Angular5

Проблема с пост-запросом/ Angular5

Есть сервис с пост-запросом:

135
Проверка на содержание слова в url

Проверка на содержание слова в url

У меня есть две ссылки на страницы, на одной из которых надо показать картинку, а на другой наоборот не показывать

187
SyntaxError: Unexpected token . [Gulp]

SyntaxError: Unexpected token . [Gulp]

Пишу простенькое приложение на Electronjs

202