Перевірте, чи завантажено зображення (немає помилок) за допомогою jQuery


224

Я використовую JavaScript з бібліотекою jQuery для обробки ескізів зображень, що містяться у списку, що не впорядковується. Коли зображення завантажується, це робить одне, коли виникає помилка, він робить щось інше. Я використовую jQuery load()та error()методи як події. Після цих подій я перевіряю елемент DOM зображення на .complete, щоб переконатися, що зображення ще не було завантажене, перш ніж jQuery зможе зареєструвати події.

Він працює правильно, за винятком випадків, коли виникає помилка, перш ніж jQuery може зареєструвати події. Єдине рішення, про яке я можу придумати, - це використовувати onerrorатрибут img для зберігання "прапора" десь у всьому світі (або на вузлі, який я є власним), який говорить про те, що він не вдався, тому jQuery може перевірити, що "store / node" при перевірці .complete.

Хтось має краще рішення?

Редагувати: Помічені основні моменти та додані додаткові деталі нижче: Я перевіряю, чи зображення завершено (він же завантажений) ПІСЛЯ я додаю на зображення подію завантаження та помилки. Таким чином, якщо зображення було завантажено до реєстрації подій, я все одно буду знати. Якщо зображення не завантажується після подій, то події подбають про нього, коли це відбувається. Проблема в цьому полягає в тому, що я легко перевіряю, чи вже завантажено зображення, але я не можу сказати, чи сталася помилка замість цього.


Коли ви реєструєте події jQuery? Можливо, деякі коди допоможуть. :)
okw

У них багато коду, те, що я сказав вище, - це просто дуже проста версія того, що я роблю. Я викликаю події після завантаження 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ліній. В іншому випадку ви ризикуєте, що зображення може завантажитися (або зіткнутися з помилкою) до того, як ці зворотні дзвінки будуть додані, і вони не будуть викликані.
callum

19
@Xavi Chrome - не самий роздратований веб-переглядач, спробуйте розробити для Internet Explorer 7 або менше. Окрім додавання параметру $ _GET до завантаження зображення, кожен раз буде завантажувати нове зображення, як запропоновано Gromix.
SSH Це

10
Ці .load()та .error()методи заплутані і тепер засуджуються, використання .on()і використовувати loadі errorяк події.
Фірш - 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;
}

1
Цікаво, що я раніше дивився на цю посаду і не розумів, що вони роблять! Повна для IE, оскільки naturalWidth не визначений в IE. Зараз збираюся перевірити.
Вільям

3
Мабуть, це працює надійно лише з першого разу. Якщо потім змінити src зображення, принаймні safari mobile буде постійно повідомляти про перше значення як для naturalWidth, так і для повного.
giorgian

5
return img.complete && typeof img.naturalWidth! = 'undefined' && img.naturalWidth! = 0;
Адріан Зелі

5
@vsync, ви, ймовірно, хочете використовувати це як одноразову перевірку, і якщо зображення ще не завантажилося, встановіть обробник подій "load". Не повинно бути забивати процесор, виконуючи цю перевірку кілька разів.
Майкл Мартін-Смукер

2
Для тих, хто цікавиться, це дуже точно те, що робить бібліотека зображень, завантажених нижче. Тож для разового
cincodenada

57

Грунтуючись на моєму розумінні в HTML специфікації W3C для imgелемента , ви повинні бути в змозі зробити це , використовуючи комбінацію completeі naturalHeightатрибутів, наприклад , так:

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

З специфікації для completeатрибута:

Атрибут IDL завершений повинен повернути true, якщо виконано будь-яке з наступних умов:

  • Атрибут src опущено.
  • Остаточне завдання, яке ставиться в чергу джерелом завдань мережі, як тільки ресурс був отриманий, у черзі.
  • Елемент img повністю доступний.
  • Елемент img зламаний.

В іншому випадку атрибут повинен повернути помилковий.

Таким чином, по суті, completeповертає істину, якщо зображення завершено або завантажено не вдалося. Оскільки ми хочемо лише випадок, коли зображення успішно завантажено, ми також повинні перевірити nauturalHeightатрибут:

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

І availableвизначається так:

Зображення завжди знаходиться в одному з наступних станів:

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

Коли елемент img знаходиться або у частково доступному стані, або у повністю доступному стані, він вважається доступним.

Отже, якщо зображення "зламане" (не вдалося завантажити), воно буде знаходитися в порушеному стані, а не в доступному стані, таким чином naturalHeightбуде 0.

Тому перевірка imgElement.complete && imgElement.naturalHeight !== 0повинна повідомити нам, чи вдало завантажено зображення.

Докладніше про це можна прочитати в специфікації W3C HTML для imgелемента або в MDN .


1
Не працює, зображення завантажується стилем "content: url"
deathangel908

1
Схоже, це не працює у Firefox із зображеннями SVG, оскільки браузер повідомляє про природну висоту / ширину 0. Відповідна помилка: bugzilla.mozilla.org/show_bug.cgi?id=1328124
leeb

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.

Особливості:

Ресурси


Це прекрасно працювало для мене. функція checkImages (imgs) {$ (imgs) .each (функція () {$ (imgs) .imagesLoaded () .progress (функція (екземпляр, зображення) {if (image.isLoaded == false) {console.log (зображення .img.src + 'не вдалося знайти.'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242

1
начебто TON відкритих питань, які є основними помилками, і розробник, схоже, не дуже їх наздоганяє. на даний момент це абсолютно непридатно у виробничих умовах.
vsync

3
@vsync Чи читали ви деякі відкриті питання? Він реагує на майже всі вони, і більшість, здається, є невідтворюваними краєвидами, з якими мало хто стикається. У мене ніколи не було проблем з цим у виробництві.
Джош Харрісон

1
так, я використовую його сам, а іноді це не працює, тому я використовую setTimeout, щоб висвітлити випадки, коли це не
вдалося

Є вагомі причини, Чому хочеться використовувати плагін imagesLoaded: completeвластивість, здається, не підтримується чітко: не в змозі знайти надійне джерело інформації щодо підтримки браузера. completeСхоже, властивість також не має чітких специфікацій: специфікація HTML5 є єдиною згадкою про це, і вона ще є в чернетній версії під час написання. Якщо ви користуєтесь підтримкою IE9 + naturalWidthта використовуєте naturalHeightлише IE9 +, тож якщо ви використовуєте її для з'ясування завантаження зображення, вам потрібен "розумний" трюк, щоб він працював на старих браузерах, і ви повинні перевірити, чи поведінка між веб-браузером відповідає
Adrien Будь

8

Отримайте інформацію з елементів зображення на сторінці
Тестування роботи на Chrome і Firefox
Working 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 -> це французький форум


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%! Що робити, якщо ваше посилання на зображення заблоковано проксі / брандмауером або сервер зображень не відповідає? У вас все ще працює мережа :)
Sen Jacob

Це ще раз завантажить кожне зображення з сервера, перехопивши кеш (навмисно). Тож для перевірки ви (принаймні) збільшуєте пропускну здатність для всіх своїх зображень. Крім того, він перевіряє, чи існує зображення на сервері, а не те, чи було завантажено в якомусь конкретному місці. Також жоден спосіб дізнатися, коли кожне зображення завантажується.
Маріус Бальчітіс

3

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

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

Цей код повертає TRUE, коли зображення завантажується повністю та успішно. Він повертає 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
}

Відповідно до коментаря giorgian щодо публікації 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() 

1

Як я розумію, властивість .complete є нестандартною. Це може бути не універсальним ... Я зауважую, що, здається, він працює по-різному у віршах Firefox IE. Я завантажую кілька зображень у javascript, а потім перевіряю, чи завершено. У Firefox це, здається, працює чудово. У IE це не так, оскільки зображення, здається, завантажуються на інший потік. Він працює лише в тому випадку, якщо я поміщаю затримку між призначенням image.src і коли я перевіряю властивість image.complete.

Використання image.onload та image.onerror для мене теж не працює, тому що мені потрібно передати параметр, щоб знати, про яке саме зображення я говорю, коли викликається функція. Будь-який спосіб зробити це, здається, не вдається, тому що він насправді здає ту саму функцію, а не різні екземпляри однієї функції. Отже значення, яке я передаю йому для ідентифікації зображення, завжди закінчується останнім значенням у циклі. Я не можу подумати про цю проблему.

У Safari та Chrome я бачу, що image.complete є справжнім і встановлена ​​натуральна ширина, навіть коли на консолі помилки відображається 404 для цього зображення ... і я навмисно видалив це зображення, щоб перевірити це. Але вищезазначене добре працює для Firefox та IE.


Хм, це цікаво. Буду проти розміщення кодового прикладу, тому я хочу спробувати пару речей?
Хаві

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

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

Всі мої головні болі пропали!


До речі: Ви, хлопці, з stackoverflow допомогли мені вже більше ста разів. За це дуже велике спасибі!


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');
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.