Bir görüntünün jQuery ile yüklenip yüklenmediğini (hata yok) kontrol edin


224

Sıralı olmayan bir listede yer alan görüntü küçük resimlerini değiştirmek için jQuery kütüphanesi ile JavaScript kullanıyorum. Görüntü yüklendiğinde bir şey yapar, bir hata oluştuğunda başka bir şey yapar. Olaylar olarak jQuery load()ve error()yöntemleri kullanıyorum . Bu olaylardan sonra, jQuery olayları kaydetmeden önce görüntünün zaten yüklenmediğinden emin olmak için .complete görüntüsünün DOM öğesini kontrol ederim.

JQuery olayları kaydetmeden önce bir hata oluştuğu sürece doğru çalışır. Aklıma gelen tek çözüm img onerrorözniteliğini, "jquuery .complete" kontrol ederken "depola / düğümü" kontrol edebilmesi için başarısız olduğunu söyleyen bir yerde bir "bayrak" depolamak (veya kendi kendine düğüm) kullanmaktır.

Daha iyi bir çözümü olan var mı?

Düzenleme: Kalın ana noktalar ve aşağıda ek ayrıntılar eklendi: Resme bir yük ve hata olayı ekledikten SONRA bir görüntünün tamamlandığını (aka yüklendi) kontrol ediyorum. Bu şekilde, görüntü olaylar kaydedilmeden önce yüklenirse, hala bileceğim. Görüntü olaylardan sonra yüklenmezse, olay gerçekleştiğinde görüntüyle ilgilenir. Bununla ilgili sorun, bir görüntünün zaten yüklü olup olmadığını kolayca kontrol edebilirim, ancak bunun yerine bir hata olup olmadığını anlayamıyorum.


JQuery etkinliklerini ne zaman kaydedersiniz? Belki bazı kodlar yardımcı olacaktır. :)
okw

Çok fazla kod var, yukarıda söylediğim, yaptığımın çok basit bir versiyonudur. DOM yüklendikten sonra olayları çağırıyorum, küçük resimlere olay eklemek için bir yöntem çağrılır.
William

Yanıtlar:


250

Başka bir seçenek, bir bellek içi görüntü öğesi oluşturarak ve özniteliğini orijinal görüntünün orijinal özniteliğine ayarlayarak onloadve / veya onerrorolayları tetiklemektir . İşte ne demek istediğimin bir örneği:srcsrc

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

Bu yardımcı olur umarım!


27
Umduğum kadar iyi çalışmıyor gibi görünüyor. Google Chrome'da, resim zaten önbellekte olduğunda sorun yaşıyor gibi görünüyor. Load () yöntemini tetiklemez. :(
William

4
Ugg, haklısın. Chrome kesinlikle geliştirilecek en can sıkıcı tarayıcıdır. Parlaklıkta, bir çözüm bulmuş olabileceğimi düşünüyorum: görüntü kaynağını "" olarak ayarlayın ve sonra orijinal kaynağa geri ayarlayın. Cevabımı güncelleyeceğim.
Xavi

1
Sen koymalıyız .attrhattını sonra.load ve .errorhatlar. Aksi takdirde, bu geri aramalar eklenmeden önce görüntünün yüklenmesi (veya bir hatayla karşılaşılması) riski vardır ve bunlar çağrılmaz.
callum

19
@Xavi Chrome, geliştirilmesi en rahatsız edici tarayıcı değil, Internet Explorer 7 veya daha azı için geliştirmeyi deneyin. Resim yüküne $ _GET parametresi eklemenin yanı sıra, Gromix'in önerdiği gibi her seferinde yeni bir resim yükler.
SSH

10
.load()Ve .error()yöntemler kafa karıştırıcı ve şimdi, kaldırılan kullanım edilir .on()ve kullanımı loadve errorgibi olayları.
Firsh -

235

Check completeile naturalWidthsırayla içinde, mülklerinizi.

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
İlginçtir, daha önce bu gönderiye bakıyordum ve yaptıklarını fark etmedim! IE için complete, naturalWidth öğesi IE'de tanımlanmadı. Şimdi kontrol edeceğim.
William

3
Görünüşe göre, bu sadece ilk kez güvenilir bir şekilde çalışıyor. Daha sonra görüntünün src'sini değiştirirseniz, en azından safari mobile, hem naturalWidth hem de complete için ilk değeri bildirmeye devam edecektir.
giorgian

5
dönüş img.complete && typeof img.naturalWidth! = 'undefined' && img.naturalWidth! = 0;
Adrian Seeley

5
@vsync bunu büyük olasılıkla bir defalık kontrol olarak kullanmak isteyeceksiniz ve görüntü henüz yüklenmediyse bir "load" olay işleyicisi ayarlayın. Bu kontrolü birden çok kez çalıştırarak CPU'yu kırmaya gerek yoktur.
Michael Martin-Smucker

2
Meraklılar için bu, aşağıda bağlantılı imagesLoaded kütüphanesinin tam olarak yaptığı şeydir. Yani, bir kerelik kullanım için, şuna
cincodenada

58

Anlayışıma göre için W3C HTML Şartname imgelemanı , sen bir arada kullanarak bunu yapmak mümkün olmalıdır completeve naturalHeightbu nedenle gibi nitelikler:

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

completeÖzellik için spesifikasyondan :

Aşağıdaki koşullardan herhangi biri doğruysa, tamamlanmış IDL özniteliği true değerini döndürmelidir:

  • Src özelliği atlandı.
  • Kaynak getirildikten sonra ağ görev kaynağı tarafından kuyruğa alınan son görev kuyruğa alındı.
  • İmg öğesi tamamen kullanılabilir.
  • İmg öğesi bozuk.

Aksi takdirde, özellik false döndürmelidir.

Bu yüzden, esasen, completegörüntünün yüklenmesi bitirilirse veya yüklenemezse true değerini döndürür. Yalnızca görüntünün başarıyla yüklendiği durumu istediğimizden, nauturalHeightözniteliği de kontrol etmemiz gerekir :

IDL nitelikleri naturalWidthve naturalHeightgörüntü mevcuttur, ya da 0 başka ise, CSS pikseli olarak, görüntünün içsel genişliğini ve yüksekliğini dönmelidir.

Ve availableşöyle tanımlanır:

Bir img her zaman aşağıdaki durumlardan birinde bulunur:

  • Kullanılamıyor - Kullanıcı aracısı görüntü verisi almamış.
  • Kısmen kullanılabilir - Kullanıcı aracısı görüntü verilerinin bir kısmını elde etti.
  • Tamamen kullanılabilir - Kullanıcı aracısı tüm görüntü verilerini elde etmiştir ve en azından görüntü boyutları mevcuttur.
  • Bozuk - Kullanıcı aracısı, alabileceği tüm görüntü verilerini elde etti, ancak görüntü boyutlarını alacak kadar görüntünün kodunu bile çözemez (örn. Görüntü bozuk veya biçim desteklenmiyor veya veri alınamıyor) .

İmg öğesi ya kısmen kullanılabilir durumda ya da tamamen kullanılabilir durumda olduğunda kullanılabilir olduğu söylenir.

Eğer görüntü "kırık" ise (yüklenemedi), o zaman mevcut durumda değil, kırık durumda naturalHeightolacaktır , bu yüzden 0 olacaktır.

Bu nedenle, kontrol imgElement.complete && imgElement.naturalHeight !== 0bize görüntünün başarıyla yüklenip yüklenmediğini söylemelidir.

Bununlaimg ilgili daha fazla bilgiyi öğenin W3C HTML Spesifikasyonu'nda veya MDN'de okuyabilirsiniz .


1
Çalışmıyor resim "content: url" stiliyle yüklendi
deathangel908

1
Tarayıcı, doğal yüksekliği / genişliği 0 olarak bildirdiği için bu Firefox'ta SVG görüntüleri ile çalışmıyor gibi görünüyor. İlgili hata: bugzilla.mozilla.org/show_bug.cgi?id=1328124
leeb

20

Birçok farklı yol denedim ve bu benim için çalışan tek yol

//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');
});

Ayrıca, tüm görüntüler DOM'a yüklendikten ve hazır olduktan sonra tetiklenen bir geri arama işlevi ekleyebilirsiniz. Bu, dinamik olarak eklenen görüntüler için de geçerlidir. http://jsfiddle.net/kalmarsh80/nrAPk/


jsfiddle bağlantı kırık
Alex Karshin

1
Yukarıdaki ilginç okumaları test ettim ve bir avuç yaygın tarayıcıda önbelleğe alınmış / önbelleğe alınmamış testler arasında başarısız oldular. Bu cevap diğerine benzer ancak şu anda uyguladığım ve test ettiğim cevap, üzerinde çalıştığını onaylayabilirim: 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

13

imagesLoadedJavascript kütüphanesini kullanın .

Düz Javascript ve jQuery eklentisi olarak kullanılabilir.

Özellikleri:

kaynaklar


Bu benim için mükemmel çalıştı. function checkImages (imgs) {$ (imgs) .each (function () {$ (imgs) .imagesLoaded () .progress (function (örnek, resim) {if (image.isLoaded == false) {console.log (resim .img.src + 'bulunamadı.'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242

1
büyük hatalar olan TON açık sorunlara sahip gibi görünüyor ve geliştiricinin onlarla çok fazla uğraşmadığı görülüyor. şu an itibariyle, bu bir üretim ortamında tamamen kullanılamaz.
vsync

3
@vsync Açık konuların bazılarını okudunuz mu? Neredeyse hepsine cevap veriyor ve çoğu, başkalarının karşılaşamadığı çoğaltılamaz kenar vakaları gibi görünüyor. Üretimde bununla hiç bir sorun yaşamadım.
Josh Harrison

1
evet kendim kullanıyorum ve bazen işe yaramıyor, bu yüzden başarısız olduğu durumlarda bir setTimeout kullanıyorum
vsync

Bir kişinin imagesLoaded eklentisini kullanmak istemesinin iyi nedenleri vardır: completeözellik açıkça desteklenmiyor gibi görünüyor: tarayıcı desteği ile ilgili güvenilir bir bilgi kaynağı bulamıyorum. completeözellik de açık bir spesifikasyona sahip gibi görünmüyor: HTML5 spesifikasyonu bundan bahseten tek özelliktir ve hala yazarken taslak bir versiyondadır. Eğer kullanırsanız naturalWidth& naturalHeightsadece görüntü yüklü olup olmadığını öğrenmek için kullanmak eğer öyleyse, o eski tarayıcılarda çalışması için bazı "akıllı" hile ihtiyaç IE9 + desteği, & sen davranış tutarlı çapraz tarayıcı kontrol etmeli
Adrien Be

8

Sayfadaki resim öğelerinden bilgileri alma
Chrome ve Firefox
Working jsFiddle üzerinde çalışmayı test etme (sonucu görmek için konsolunuzu açın)

$('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);

});

Not: jQuery kullandım , bunun tam javascript'te başarılı olabileceğini düşündüm

Ben burada iyi bilgi bulabilirsiniz OpenClassRoom -> bu bir Fransız forumu


3

Gerçek zamanlı ağ dedektörü - sayfayı yenilemeden ağ durumunu kontrol edin: (jquery değil, test edildi ve% 100 çalışıyor: (Firefox v25.0'da test edildi))

Kod:

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

bağlantı kesilirse tekrar düğmesine basın.

Güncelleme 1: Sayfayı yenilemeden otomatik algılama:

<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%! Resim bağlantınız bir proxy / güvenlik duvarı tarafından engellenirse veya resim sunucusu yanıt vermiyorsa ne olur? Hala ağ çalışıyor :)
Sen Jacob

Bu, her görüntüyü sunucudan bir kez daha yükler ve önbelleği bozar (kasıtlı olarak). Yani sadece kontrol etmek için, tüm görüntüleriniz için (en azından) bant genişliğini iki katına çıkarıyorsunuz. Ayrıca, görüntünün sunucuda olup olmadığını belirli bir yere yüklenmiş olup olmadığını kontrol eder. Ayrıca her görüntünün ne zaman yüklendiğini bilmenin hiçbir yolu yoktur.
Marius Balčytis

3

Bu sayfadaki ilginç çözümleri okuduktan sonra, Chrome, IE, Firefox, Safari ve Opera (tümü Windows'ta). Ayrıca, kullandığım bir iPhone / iPad emülatörü üzerinde çalıştı.

Bu çözüm ile SLaks ve Noyo'nun gönderisi arasındaki en büyük fark, bu çözümün esas olarak naturalWidth ve naturalHeight özelliklerini kontrol etmesidir. Mevcut tarayıcı sürümlerinde, bu iki özelliğin en yararlı ve tutarlı sonuçları sağladığı görülüyor.

Bir görüntü tam olarak VE başarıyla yüklendiğinde bu kod TRUE değerini döndürür. Bir görüntü tam olarak yüklenmediğinde VEYA yüklenemediğinde YANLIŞ döndürür.

Dikkat etmeniz gereken bir şey, görüntü 0x0 piksel bir görüntü ise bu işlevin YANLIŞ döndüreceği yönündedir. Ancak bu görüntüler oldukça nadirdir ve henüz bir 0x0 piksel görüntüsünün henüz yüklenip yüklenmediğini görmek istediğiniz çok kullanışlı bir durum düşünemiyorum :)

İlk olarak, HTMLImageElement prototipine "isLoaded" adlı yeni bir işlev ekliyoruz, böylece işlev herhangi bir görüntü öğesinde kullanılabilir.

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;

};

Daha sonra, görüntünün yükleme durumunu kontrol etmemiz gerektiğinde, sadece "isLoaded" işlevini çağırırız.

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

Giorgian'ın SLaks ve Noyo'nun gönderisine yaptığı yorum başına, bu çözüm muhtemelen SRC özelliğini değiştirmeyi planlıyorsanız Safari Mobile'da bir kerelik kontrol olarak kullanılabilir. Ancak, var olan bir görüntü öğesindeki SRC özniteliğini değiştirmek yerine yeni bir SRC özniteliğine sahip bir görüntü öğesi oluşturarak bu sorunu çözebilirsiniz.


2

Yukarıdaki yöntemlerin bir kombinasyonunu kullanarak çapraz tarayıcı çalışmak için bu şekilde aldım (Ayrıca dom dinamik olarak görüntüleri eklemek için gerekli):

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

Not: isIE değişkeni için geçerli bir boole durumu sağlamanız gerekir.


2
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

// Veya Eklenti Olarak

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

// $(".myImage").isLoaded() 

1

Anladığım gibi .complete özelliği standart değildir. Evrensel olmayabilir ... Ben Firefox ayetleri IE farklı çalışıyor gibi görünüyor. Javascript birkaç görüntü yüklüyor sonra tamamlandı kontrol ediyorum. Firefox'ta, bu harika çalışıyor gibi görünüyor. IE'de, görüntüler başka bir iş parçacığına yükleniyor gibi görünmüyor. Yalnızca image.src'ye atamam arasında bir gecikme koyarsam ve image.complete özelliğini kontrol ettiğimde çalışır.

İmage.onload ve image.onerror kullanımı da benim için çalışmıyor, çünkü işlev çağrıldığında hangi görüntüyü konuştuğumu bilmek için bir parametre iletmem gerekiyor. Bunu yapmanın herhangi bir yolu başarısız gibi görünüyor çünkü aynı işlevin farklı örneklerini değil, aynı işlevi geçiyor gibi görünüyor. Bu yüzden görüntüyü tanımlamak için içine aktardığım değer her zaman döngüdeki son değer olur. Bu soruna hiçbir şekilde bakamıyorum.

Safari ve Chrome'da, hata konsolu bu görüntü için bir 404 gösterdiğinde bile image.complete true ve naturalWidth ayarını görüyorum ... ve bunu test etmek için bilerek bu görüntüyü kaldırdım. Ancak yukarıdaki Firefox ve IE için iyi çalışıyor.


Hmm, bu ilginç. Birkaç şey denemek istiyorum bu yüzden bir kod örneği gönderme ister misiniz?
Xavi

1

Bu kod snippet'i, tarayıcı önbelleğe alma sorunlarını düzeltmeme yardımcı oldu:

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

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

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

Tarayıcı önbelleği devre dışı bırakıldığında, yalnızca bu kod çalışmaz:

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

çalışmasını sağlamak için eklemeniz gerekir:

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

0

Bu JavaScriptkodu kullanarak görüntünün başarıyla yüklendiğini kontrol edebilirsiniz.

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

Bunu dene


0

Bir görüntünün ve EventListener'ın tam yüküyle ilgili birçok sorun yaşadım.

Ne denediysem sonuçlar güvenilir değildi.

Ama sonra çözümü buldum. Teknik olarak hoş değil, ama şimdi hiç başarısız bir görüntü yüküm olmadı.

Ben ne yaptım:

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

Görüntüyü bir kez yüklemek yerine, ilk defadan sonra doğrudan ikinci kez yüklüyorum ve her ikisi de olay işleyicisinden geçiyor.

Tüm baş ağrılarım gitti!


Bu arada: stackoverflow'dan sizler yüzlerce kez bana zaten yardımcı oldunuz. Bunun için çok büyük bir teşekkür ederim!


0

Bu benim için iyi çalıştı :)

$('.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');
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.