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

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

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

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

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

14 ответов

Решение

Другой вариант - вызвать 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"))
;

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

Проверить 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;
}

Основываясь на моем понимании спецификации W3C HTML для 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.

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

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

Использование imagesLoaded библиотека JavaScript

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

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

Ресурсы

Получить информацию из элементов изображения на странице
Тест работы на 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 -> это французский форум

Прочитав интересные решения на этой странице, я создал простое в использовании решение, на которое сильно повлияли записи 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 в существующем элементе изображения.

Детектор сети в реальном времени - проверьте состояние сети, не обновляя страницу:(это не 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>

Вот как я заставил его работать в кросс-браузерной системе, используя комбинацию из описанных выше методов (мне также нужно было динамически вставлять изображения в 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.

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() 

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

$("#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();
});

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

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

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

У меня было много проблем с полной загрузкой изображения и 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");
                }

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

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


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

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

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

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

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

$('.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');
});
Другие вопросы по тегам