Проверьте, загружено ли изображение (без ошибок) с помощью jQuery

224

Я использую JavaScript с библиотекой jQuery для управления миниатюрами изображений, содержащимися в неупорядоченном списке. Когда изображение загружается, оно делает одно, а при возникновении ошибки - другое. Я использую jQuery load()и error()методы в качестве событий. После этих событий я проверяю DOM-элемент image на наличие .complete, чтобы убедиться, что изображение еще не загружено, прежде чем jQuery сможет зарегистрировать события.

Он работает правильно, за исключением случаев, когда возникает ошибка, прежде чем jQuery сможет зарегистрировать события. Единственное решение, которое я могу придумать, - это использовать onerrorатрибут img для хранения «флага» где-то на глобальном уровне (или на самом узле), который говорит, что произошел сбой, поэтому jQuery может проверить этот «store / node» при проверке .complete.

У кого-нибудь есть лучшее решение?

Редактировать: Основные точки выделены жирным шрифтом и добавлены дополнительные подробности ниже: Я проверяю, завершено ли изображение (оно также загружено) ПОСЛЕ того, как я добавляю на изображение событие загрузки и ошибки. Таким образом, если изображение было загружено до регистрации событий, я все равно буду знать. Если изображение не загружается после событий, события позаботятся об этом, когда это произойдет. Проблема в том, что я могу легко проверить, загружено ли изображение, но не могу сказать, произошла ли ошибка.

Уильям
источник
Когда вы регистрируете события jQuery? Может быть, некоторые коды помогут. :)
ОК
Theres много кода, то, что я сказал выше, это просто очень простая версия того, что я делаю. Я вызываю события после загрузки DOM, вызывается метод для добавления событий к миниатюрам.
Уильям

Ответы:

250

Другим вариантом является запуск событий onloadи / или onerrorсобытий путем создания элемента изображения в памяти и установки его srcатрибута в качестве исходного srcатрибута исходного изображения. Вот пример того, что я имею в виду:

$("<img/>")
    .on('load', function() { console.log("image loaded correctly"); })
    .on('error', function() { console.log("error loading image"); })
    .attr("src", $(originalImage).attr("src"))
;

Надеюсь это поможет!

Хави
источник
27
Кажется, не работает так, как я надеялся. В Google Chrome, похоже, возникают проблемы, когда изображение уже находится в кеше. Это не вызывает метод load (). :(
Уильям
4
Угг, ты прав. Chrome, безусловно, самый раздражающий браузер для разработки. На ярком, я думаю, я мог бы найти обходной путь: установить источник изображения на «», а затем вернуться к исходному источнику. Я обновлю свой ответ.
Хави
1
Вы должны поместить .attrстроку после.load и .errorлиний. В противном случае вы рискуете загрузить изображение (или столкнуться с ошибкой) до того, как эти обратные вызовы будут добавлены, и они не будут вызваны.
Каллум
19
@Xavi Chrome - не самый надоедливый браузер для разработки, попробуйте разработку для Internet Explorer 7 или менее. Помимо добавления параметра $ _GET к загрузке изображения, каждый раз будет загружаться новое изображение, как предложил Gromix.
SSH Это
10
Эти .load()и .error()методы запутанные и теперь осуждаются, использование .on()и использовать loadи errorкак события.
Firsh - LetsWP.io
235

Проверьте completeи naturalWidthсвойства, в этом порядке.

https://stereochro.me/ideas/detecting-broken-images-js

function IsImageOk(img) {
    // During the onload event, IE correctly identifies any images that
    // weren’t downloaded as not complete. Others should too. Gecko-based
    // browsers act like NS4 in that they report this incorrectly.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth and
    // naturalHeight. These give the true size of the image. If it failed
    // to load, either of these should be zero.
    if (img.naturalWidth === 0) {
        return false;
    }

    // No other way of checking: assume it’s ok.
    return true;
}
SLaks
источник
1
Интересно, что я смотрел на этот пост ранее, и я не понимал, что они делают! завершено для IE, так как натуральная ширина не определена в IE. Собираюсь проверить это сейчас.
Уильям
3
По-видимому, это работает надежно только в первый раз. Если вы затем измените src изображения, по крайней мере, Safari Mobile будет сообщать о первом значении для NaturalWidth и complete.
Георгий
5
return img.complete && typeof img.naturalWidth! = 'undefined' && img.naturalWidth! = 0;
Адриан Сили
5
@vsync, вы, вероятно, захотите использовать это как одноразовую проверку, и если изображение еще не загружено, установите обработчик события «загрузка». Там не должно быть необходимости забивать процессор, выполняя эту проверку несколько раз.
Майкл Мартин-Смукер
2
Для тех, кому интересно, это в значительной степени именно то, что делает библиотека imagesLoaded, связанная ниже. Итак, для одноразового использования, пойти на это: github.com/desandro/imagesloaded/blob/master/…
cincodenada
57

Основываясь на моем понимании в HTML спецификации W3C для imgэлемента , вы должны быть в состоянии сделать это , используя комбинацию completeи naturalHeightатрибутов, например , так:

function imgLoaded(imgElement) {
  return imgElement.complete && imgElement.naturalHeight !== 0;
}

Из спецификации для completeатрибута:

Атрибут IDL complete должен возвращать true, если выполняется любое из следующих условий:

  • Атрибут src опущен.
  • Последняя задача, поставленная в очередь источником сетевых задач после извлечения ресурса, была поставлена ​​в очередь.
  • Элемент img полностью доступен.
  • Элемент img не работает.

В противном случае атрибут должен возвращать false.

По сути, completeвозвращает true, если изображение либо завершило загрузку, либо не удалось загрузить. Поскольку нам нужен только тот случай, когда изображение успешно загружено, нам нужно также проверить nauturalHeightатрибут:

Атрибуты IDL naturalWidthи naturalHeightдолжны возвращать собственную ширину и высоту изображения в пикселях CSS, если изображение доступно, иначе 0.

И availableопределяется так:

Img всегда находится в одном из следующих состояний:

  • Недоступно - пользовательский агент не получил никаких данных изображения.
  • Частично доступно - пользовательский агент получил некоторые данные изображения.
  • Полностью доступно - Пользовательский агент получил все данные изображения, и, по крайней мере, доступны размеры изображения.
  • Сломан - пользовательский агент получил все данные изображения, которые он может, но он даже не может декодировать изображение настолько, чтобы получить размеры изображения (например, изображение повреждено, или формат не поддерживается, или данные не могут быть получены) ,

Когда элемент img находится либо в частично доступном состоянии, либо в полностью доступном состоянии, он считается доступным.

Поэтому, если изображение «повреждено» (не удалось загрузить), оно будет в поврежденном состоянии, а не в доступном состоянии, поэтому naturalHeightбудет 0.

Поэтому проверка imgElement.complete && imgElement.naturalHeight !== 0должна сообщить нам, успешно ли загружено изображение.

Подробнее об этом можно прочитать в HTML-спецификации W3C для imgэлемента или в MDN .

Ajedi32
источник
1
Не работа изображение загружается в стиле «содержание: URL»
deathangel908
1
Это не похоже на работу в Firefox с SVG изображений в браузер передает естественную высоту / ширину , чтобы быть 0. Соответствующая ошибка: bugzilla.mozilla.org/show_bug.cgi?id=1328124
Лееб
20

Я пробовал много разных способов, и этот способ - единственный, который работал для меня

//check all images on the page
$('img').each(function(){
    var img = new Image();
    img.onload = function() {
        console.log($(this).attr('src') + ' - done!');
    }
    img.src = $(this).attr('src');
});

Вы также можете добавить функцию обратного вызова, сработавшую, когда все изображения загружены в DOM и готовы. Это относится и к динамически добавляемым изображениям. http://jsfiddle.net/kalmarsh80/nrAPk/

Кал
источник
Ссылка jsfiddle не работает
Алекс Каршин
1
Я проверил интересные чтения выше, и они терпят неудачу между кэшированными / некэшированными тестами в нескольких распространенных браузерах. Этот ответ похож на другой, но тот, который я внедрил и протестировал только сейчас, могу подтвердить, что он работает: EdgeWin10, IE11Win8.1, Win7IE10, Win7IE9, iOS 10.2 Chrome, iOS 10.2 Safari, Mac OS 10.12 Chrome, Mac OS 10.12 Safari, Mac OS 10.12 Firefox, Google Pixel 7.1, Samsung S5 Android 4.4. Не забудьте также использовать addEventListener / removeEventListener: D
danjah
13

Используйте imagesLoadedбиблиотеку JavaScript .

Используется с простым Javascript и как плагин jQuery.

Особенности:

Ресурсы

Джош Харрисон
источник
Это отлично сработало для меня. function checkImages (imgs) {$ (imgs) .each (function () {$ (imgs) .imagesLoaded () .progress (function (instance, image) {if (image.isLoaded == false) {console.log (image .img.src + 'не найден.'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242
1
Похоже, у него есть множество открытых проблем, которые приводят к серьезным ошибкам, и разработчик, похоже, не слишком их догоняет. на данный момент это совершенно непригодно для использования в производственной среде.
vsync
3
@vsync Вы читали некоторые открытые вопросы? Он отвечает почти на все из них, и большинство из них кажутся невоспроизводимыми крайними случаями, с которыми сталкиваются немногие. У меня никогда не было проблем с этим на производстве.
Джош Харрисон
1
да, я использую его сам, и иногда он не работает, поэтому я использую setTimeout для покрытия случаев, когда он терпит неудачу
vsync
Существуют веские причины, по которым кто-то хочет использовать плагин imagesLoaded: completeсвойство явно не поддерживается: невозможно найти надежный источник информации о поддержке браузера. completeСвойство также, похоже, не имеет четкой спецификации: спецификация HTML5 - единственная, упоминающая об этом, и она все еще находится в черновой версии на момент написания. Если вы используете naturalWidthи naturalHeightподдерживаете только IE9 +, поэтому, если вы используете его, чтобы узнать, загружено ли изображение, вам понадобится какой-нибудь «умный» трюк, чтобы заставить его работать в старых браузерах, и вы должны проверить, что кросс-браузерное поведение согласованно
Adrien Быть
8

Получить информацию из элементов изображения на странице.
Тестирование работы в Chrome и Firefox.
Работа с jsFiddle (откройте консоль, чтобы увидеть результат)

$('img').each(function(){ // selecting all image element on the page

    var img = new Image($(this)); // creating image element

    img.onload = function() { // trigger if the image was loaded
        console.log($(this).attr('src') + ' - done!');
    }

    img.onerror = function() { // trigger if the image wasn't loaded
        console.log($(this).attr('src') + ' - error!');
    }

    img.onAbort = function() { // trigger if the image load was abort
        console.log($(this).attr('src') + ' - abort!');
    }

    img.src = $(this).attr('src'); // pass src to image object

    // log image attributes
    console.log(img.src);
    console.log(img.width);
    console.log(img.height);
    console.log(img.complete);

});

Примечание: я использовал jQuery , я думал, что это может быть достигнуто на полном JavaScript

Я нахожу хорошую информацию здесь OpenClassRoom -> это французский форум

Julha
источник
3

Детектор сети в реальном времени - проверьте состояние сети, не обновляя страницу: (это не jquery, но протестировано и работает на 100%: (протестировано на Firefox v25.0))

Код:

<script>
 function ImgLoad(myobj){
   var randomNum = Math.round(Math.random() * 10000);
   var oImg=new Image;
   oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
   oImg.onload=function(){alert('Image succesfully loaded!')}
   oImg.onerror=function(){alert('No network connection or image is not available.')}
}
window.onload=ImgLoad();
</script>

<button id="reloadbtn" onclick="ImgLoad();">Again!</button>

если соединение потеряно, просто нажмите кнопку «Снова».

Обновление 1: автоопределение без обновления страницы:

<script>
     function ImgLoad(myobj){
       var randomNum = Math.round(Math.random() * 10000);
       var oImg=new Image;
       oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
       oImg.onload=function(){networkstatus_div.innerHTML="";}
       oImg.onerror=function(){networkstatus_div.innerHTML="Service is not available. Please check your Internet connection!";}
}

networkchecker = window.setInterval(function(){window.onload=ImgLoad()},1000);
</script>

<div id="networkstatus_div"></div>
Дженей Тамас
источник
100%! Что если ссылка на изображение заблокирована прокси / брандмауэром или сервер изображений не отвечает? Вы все еще работаете в сети :)
Сен Джейкоб
Это будет загружать каждое изображение еще раз с сервера, разрушая кэш (намеренно). Так что просто для проверки, вы (по крайней мере) удваивает пропускную способность для всех ваших изображений. Кроме того, он проверяет, существует ли изображение на сервере, а не загружено ли оно в каком-то определенном месте. Также нет способа узнать, когда загружается каждое изображение.
Мариус Балчитис
3

Прочитав интересные решения на этой странице, я создал простое в использовании решение, на которое сильно повлияли заметки SLaks и Noyo, которые, кажется, работают над довольно свежими (на момент написания) версиями Chrome, IE, Firefox, Safari и Опера (все на Windows). Кроме того, он работал на эмуляторе iPhone / iPad, который я использовал.

Одно из основных различий между этим решением и SLaks и публикацией Noyo заключается в том, что это решение в основном проверяет свойства naturalWidth и naturalHeight. Я обнаружил, что в текущих версиях браузера эти два свойства обеспечивают наиболее полезные и согласованные результаты.

Этот код возвращает TRUE, когда изображение полностью загружено и успешно. Он возвращает FALSE, когда изображение либо не загружено полностью, либо ИЛИ не удалось загрузить.

Одна вещь, о которой вам нужно знать, это то, что эта функция также возвращает FALSE, если изображение является пиксельным изображением 0x0. Но эти изображения довольно необычны, и я не могу вспомнить очень полезного случая, когда вы хотели бы проверить, загрузилось ли уже изображение с пикселем 0x0 :)

Сначала мы прикрепляем новую функцию isLoaded к прототипу HTMLImageElement, чтобы эту функцию можно было использовать с любым элементом изображения.

HTMLImageElement.prototype.isLoaded = function() {

    // See if "naturalWidth" and "naturalHeight" properties are available.
    if (typeof this.naturalWidth == 'number' && typeof this.naturalHeight == 'number')
        return !(this.naturalWidth == 0 && this.naturalHeight == 0);

    // See if "complete" property is available.
    else if (typeof this.complete == 'boolean')
        return this.complete;

    // Fallback behavior: return TRUE.
    else
        return true;

};

Затем, в любое время, когда нам нужно проверить состояние загрузки изображения, мы просто вызываем функцию isLoaded.

if (someImgElement.isLoaded()) {
    // YAY! The image loaded
}
else {
    // Image has not loaded yet
}

Согласно комментариям Джорджа о записи SLaks и Noyo, это решение, вероятно, можно использовать в качестве одноразовой проверки в Safari Mobile, если вы планируете изменить атрибут SRC. Но вы можете обойти это, создав элемент изображения с новым атрибутом SRC вместо изменения атрибута SRC в существующем элементе изображения.

Данные дан
источник
2

Вот как я заставил его работать в кросс-браузерном режиме, используя комбинацию описанных выше методов (мне также нужно было динамически вставлять изображения в DOM):

$('#domTarget').html('<img src="" />');

var url = '/some/image/path.png';

$('#domTarget img').load(function(){}).attr('src', url).error(function() {
    if ( isIE ) {
       var thisImg = this;
       setTimeout(function() {
          if ( ! thisImg.complete ) {
             $(thisImg).attr('src', '/web/css/img/picture-broken-url.png');
          }
       },250);
    } else {
       $(this).attr('src', '/web/css/img/picture-broken-url.png');
    }
});

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

Джастин Винсент
источник
2
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

// Или как плагин

    $.fn.extend({
      isLoaded: function(){
        return this.prop("complete") && this.prop("naturalWidth") !== 0;
      }
    })

// $(".myImage").isLoaded() 
KhaledDev
источник
1

Как я понимаю, свойство .complete нестандартно. Это не может быть универсальным ... Я замечаю, что в Firefox, IE, кажется, он работает по-другому. Я загружаю несколько изображений в JavaScript, а затем проверяю, завершено ли. В Firefox это работает отлично. В IE это не так, потому что изображения загружаются в другой поток. Это работает, только если я помещаю задержку между моим назначением для image.src и когда я проверяю свойство image.complete.

Использование image.onload и image.onerror также не работает для меня, потому что мне нужно передать параметр, чтобы знать, о каком изображении я говорю, когда вызывается функция. Кажется, что любой способ сделать это потерпел неудачу, потому что фактически он передает одну и ту же функцию, а не разные экземпляры одной и той же функции. Таким образом, значение, которое я передаю, чтобы идентифицировать изображение, всегда оказывается последним значением в цикле. Я не могу придумать способ обойти эту проблему.

В Safari и Chrome я вижу true для image.complete и значение NaturalWidth, даже когда консоль ошибок отображает 404 для этого изображения ... и я намеренно удалил это изображение, чтобы проверить это. Но вышесказанное хорошо работает для Firefox и IE.

user1018645
источник
Хм, это интересно. Не могли бы вы опубликовать пример кода, чтобы я попробовал пару вещей?
Хави
1

Этот фрагмент кода помог мне исправить проблемы с кэшированием в браузере:

$("#my_image").on('load', function() {

    console.log("image loaded correctly"); 
}).each(function() {

     if($(this).prop('complete')) $(this).load();
});

Когда кеш браузера отключен, только этот код не работает:

$("#my_image").on('load', function() {
     console.log("image loaded correctly"); 
})

чтобы это работало, нужно добавить:

.each(function() {
     if($(this).prop('complete')) $(this).load();
});
Фрэнк
источник
0

Используя этот JavaScriptкод, вы можете проверить, успешно ли загружено изображение.

document.onready = function(e) {
        var imageobj = new Image();
        imageobj.src = document.getElementById('img-id').src;
        if(!imageobj.complete){ 
            alert(imageobj.src+"  -  Not Found");
        }
}

Попробуйте это

Аджай Гупта
источник
0

У меня было много проблем с полной загрузкой изображения и EventListener.

Что бы я ни пытался, результаты не были надежными.

Но потом я нашел решение. Технически это не очень хорошо, но теперь у меня никогда не было неудачной загрузки изображения.

Что я сделал:

                    document.getElementById(currentImgID).addEventListener("load", loadListener1);
                    document.getElementById(currentImgID).addEventListener("load", loadListener2);

                function loadListener1()
                    {
                    // Load again
                    }

                function loadListener2()
                {
                    var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
                    alert("Image loaded");
                }

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

Все мои головные боли ушли!


Кстати, вы, ребята из stackoverflow, помогали мне уже более ста раз. За это очень большое спасибо!

Scoobeedo Cool
источник
0

Этот работал хорошо для меня :)

$('.progress-image').each(function(){
    var img = new Image();
    img.onload = function() {
        let imgSrc = $(this).attr('src');
        $('.progress-image').each(function(){
            if($(this).attr('src') == imgSrc){
                console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
            }
        })
    }
    img.src = $(this).attr('src');
});
Каннан Утхаман
источник