Periksa apakah gambar dimuat (tidak ada kesalahan) dengan jQuery

224

Saya menggunakan JavaScript dengan pustaka jQuery untuk memanipulasi gambar mini gambar yang terdapat dalam daftar tidak berurutan. Ketika gambar dimuat itu melakukan satu hal, ketika kesalahan terjadi itu melakukan sesuatu yang lain. Saya menggunakan jQuery load()dan error()metode sebagai acara. Setelah peristiwa ini, saya memeriksa elemen DOM gambar untuk .complete untuk memastikan gambar belum dimuat sebelum jQuery bisa mendaftarkan acara.

Ini berfungsi dengan benar kecuali ketika kesalahan terjadi sebelum jQuery dapat mendaftarkan acara. Satu-satunya solusi yang dapat saya pikirkan adalah dengan menggunakan onerroratribut img untuk menyimpan "flag" di suatu tempat secara global (atau pada node itu sendiri) yang mengatakan itu gagal sehingga jQuery dapat memeriksa "store / node" itu ketika memeriksa .complete.

Adakah yang punya solusi yang lebih baik?

Sunting: Poin utama yang dicetak tebal dan menambahkan detail ekstra di bawah: Saya memeriksa apakah gambar sudah selesai (alias dimuat) SETELAH saya menambahkan acara memuat dan kesalahan pada gambar. Dengan begitu, jika gambar dimuat sebelum acara didaftarkan, saya akan tetap tahu. Jika gambar tidak dimuat setelah acara maka acara akan mengurusnya ketika itu terjadi. Masalahnya adalah, saya dapat dengan mudah memeriksa apakah suatu gambar sudah dimuat, tetapi saya tidak bisa memastikan apakah ada kesalahan yang terjadi.

William
sumber
Kapan Anda mendaftarkan acara jQuery? Mungkin beberapa kode akan membantu. :)
okw
Ada banyak kode, apa yang saya katakan di atas hanyalah versi yang sangat sederhana dari apa yang saya lakukan. Saya memanggil acara setelah DOM dimuat, metode dipanggil untuk menambahkan acara ke thumbnail.
William

Jawaban:

250

Pilihan lain adalah untuk memicu onloaddan / atau onerrorperistiwa dengan membuat elemen gambar dalam memori dan mengatur srcatributnya ke srcatribut asli dari gambar asli. Berikut ini contoh yang saya maksud:

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

Semoga ini membantu!

Xavi
sumber
27
Sepertinya tidak berfungsi sebaik yang saya harapkan. Di Google Chrome sepertinya ada masalah ketika gambar sudah dalam cache. Itu tidak memicu metode load (). :(
William
4
Ugg, kamu benar. Chrome jelas merupakan browser yang paling menjengkelkan untuk dikembangkan. Pada terang, saya pikir saya mungkin telah menemukan pekerjaan: atur sumber gambar ke "" lalu kembali ke sumber aslinya. Saya akan memperbarui jawaban saya.
Xavi
1
Anda harus meletakkan .attrbaris setelah itu .loaddan .errorgaris. Kalau tidak, Anda berisiko bahwa gambar mungkin memuat (atau menemukan kesalahan) sebelum panggilan balik itu ditambahkan, dan mereka tidak akan dipanggil.
callum
19
@Xavi Chrome bukan browser yang paling menjengkelkan untuk dikembangkan, coba kembangkan untuk Internet Explorer 7 atau kurang. Selain menambahkan parameter $ _GET ke beban gambar, akan memuat gambar baru setiap kali, seperti yang disarankan Gromix.
SSH Ini
10
Metode .load()dan .error()membingungkan dan sekarang ditinggalkan, menggunakan .on()dan menggunakan loaddan errorsebagai acara.
Firsh - LetsWP.io
235

Periksa completedan naturalWidthproperti, dalam urutan itu.

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
sumber
1
Menarik, saya melihat posting itu sebelumnya dan saya tidak menyadari bahwa mereka melakukannya! lengkap untuk IE karena naturalWidth tidak didefinisikan dalam IE. Akan memeriksanya sekarang.
William
3
Rupanya, ini hanya bekerja andal pertama kali. Jika Anda kemudian mengubah src gambar, setidaknya safari mobile akan terus melaporkan nilai pertama untuk naturalWidth dan lengkap.
giorgian
5
return img.complete && typeof img.naturalWidth! = 'tidak terdefinisi' && img.naturalWidth! = 0;
Adrian Seeley
5
@vsync Anda mungkin ingin menggunakan ini sebagai pemeriksaan satu kali, dan jika gambar belum dimuat, siapkan event handler "load". Seharusnya tidak perlu ada palu CPU dengan menjalankan pemeriksaan ini beberapa kali.
Michael Martin-Smucker
2
Bagi mereka yang penasaran, ini persis seperti yang dilakukan oleh perpustakaan imagesLoaded di bawah ini. Jadi, untuk penggunaan sekali saja, lakukan: github.com/desandro/imagesloaded/blob/master/…
cincodenada
57

Berdasarkan pemahaman saya tentang Spesifikasi HTML W3C untuk imgelemen , Anda harus dapat melakukan ini menggunakan kombinasi atribut completedan naturalHeight, seperti:

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

Dari spec untuk completeatribut:

Atribut IDL selesai harus mengembalikan true jika salah satu dari kondisi berikut ini benar:

  • Atribut src dihilangkan.
  • Tugas terakhir yang di-antri oleh sumber tugas jaringan setelah sumber daya diambil telah di-antri.
  • Elemen img sepenuhnya tersedia.
  • Elemen img rusak.

Jika tidak, atribut harus mengembalikan false.

Jadi pada dasarnya, completemengembalikan true jika gambar telah selesai memuat, atau gagal memuat. Karena kita hanya menginginkan case di mana gambar berhasil dimuat, kita perlu memeriksa nauturalHeightatributnya juga:

IDL mengaitkan naturalWidthdan naturalHeightharus mengembalikan lebar dan tinggi intrinsik gambar, dalam piksel CSS, jika gambar tersedia, atau 0.

Dan availabledidefinisikan seperti ini:

Seorang img selalu berada di salah satu negara berikut:

  • Tidak tersedia - Agen pengguna belum mendapatkan data gambar apa pun.
  • Tersedia sebagian - Agen pengguna telah memperoleh beberapa data gambar.
  • Tersedia sepenuhnya - Agen pengguna telah memperoleh semua data gambar dan setidaknya dimensi gambar tersedia.
  • Rusak - Agen pengguna telah memperoleh semua data gambar yang dapat, tetapi bahkan tidak dapat mendekode gambar cukup untuk mendapatkan dimensi gambar (misalnya gambar rusak, atau format tidak didukung, atau tidak ada data yang bisa diperoleh) .

Ketika elemen img baik dalam kondisi sebagian tersedia atau dalam kondisi sepenuhnya tersedia, dikatakan tersedia.

Jadi jika gambar "rusak" (gagal dimuat), maka gambar itu akan dalam keadaan rusak, bukan keadaan yang tersedia, jadi naturalHeightakan menjadi 0.

Karena itu, pengecekan imgElement.complete && imgElement.naturalHeight !== 0harus memberi tahu kami apakah gambar telah berhasil dimuat.

Anda dapat membaca lebih lanjut tentang ini di Spesifikasi HTML W3C untuk imgelemen , atau di MDN .

Ajedi32
sumber
1
Tidak berfungsi adalah gambar dimuat dengan gaya "content: url"
deathangel908
1
Ini tampaknya tidak berfungsi di Firefox dengan gambar SVG karena browser melaporkan tinggi / lebar alami menjadi 0. Bug yang relevan: bugzilla.mozilla.org/show_bug.cgi?id=1328124
leeb
20

Saya mencoba berbagai cara dan cara ini adalah satu-satunya yang berhasil untuk saya

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

Anda juga dapat menambahkan fungsi panggilan balik yang dipicu setelah semua gambar dimuat di DOM dan siap. Ini berlaku untuk gambar yang ditambahkan secara dinamis juga. http://jsfiddle.net/kalmarsh80/nrAPk/

Kal
sumber
jsfiddle tautan rusak
Alex Karshin
1
Saya telah menguji bacaan menarik di atas dan gagal di antara tes cache / tidak di-cache pada beberapa browser umum. Jawaban ini mirip dengan yang lain tetapi yang saya terapkan & teruji sekarang, saya dapat mengonfirmasi itu berfungsi pada: 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. Jangan lupa untuk menggunakan addEventListener / removeEventListener juga: D
danjah
13

Gunakan imagesLoadedperpustakaan javascript .

Dapat digunakan dengan Javascript biasa dan sebagai plugin jQuery.

Fitur:

Sumber daya

Josh Harrison
sumber
Ini bekerja dengan baik untuk saya. function checkImages (imgs) {$ (imgs) .each (function () {$ (imgs) .imagesLoaded () .progress (function (instance, image) {if (image.isLoaded == false) {console.log (image .img.src + 'tidak dapat ditemukan.'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242
1
tampaknya memiliki BANYAK masalah terbuka yang bug utama, dan pengembang tampaknya tidak berbuat banyak mengejar mereka. seperti yang sekarang, ini benar-benar tidak dapat digunakan dalam lingkungan produksi.
vsync
3
@vsync Sudahkah Anda membaca beberapa masalah terbuka? Dia menanggapi hampir semua dari mereka, dan sebagian besar tampaknya kasus-kasus tepi yang tidak dapat diproduksi kembali yang dihadapi oleh beberapa orang lainnya. Saya tidak pernah punya masalah dengan itu dalam produksi.
Josh Harrison
1
ya saya menggunakannya sendiri dan kadang-kadang tidak berfungsi, jadi saya menggunakan setTimeout untuk membahas kasus-kasus yang gagal
vsync
Ada alasan bagus MENGAPA seseorang ingin menggunakan plugin imagesLoaded: completeproperti tampaknya tidak didukung dengan jelas: tidak dapat menemukan sumber info yang dapat dipercaya mengenai dukungan browser. completeproperti juga tampaknya tidak memiliki spesifikasi yang jelas: spesifikasi HTML5 adalah satu-satunya yang menyebutkannya & masih dalam versi konsep pada saat penulisan. Jika Anda menggunakan naturalWidth& naturalHeighthanya memiliki dukungan IE9 +, jadi jika Anda menggunakannya untuk mengetahui apakah gambar tersebut dimuat, Anda memerlukan beberapa trik "pintar" untuk membuatnya berfungsi di browser lama, & Anda harus memeriksa perilaku lintas-browser konsisten
Adrien Jadilah
8

Ambil informasi dari elemen gambar di halaman.
Tes bekerja di Chrome dan Firefox.
Bekerja jsFiddle (buka konsol Anda untuk melihat hasilnya)

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

});

Catatan: Saya menggunakan jQuery , saya pikir ini dapat mencapai javascript penuh

Saya menemukan informasi yang bagus di sini OpenClassRoom -> ini adalah forum Perancis

Julha
sumber
3

Detektor jaringan waktu nyata - periksa status jaringan tanpa menyegarkan halaman: (ini bukan jquery, tetapi diuji, dan 100% berfungsi: (diuji pada Firefox v25.0))

Kode:

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

jika koneksi terputus cukup tekan tombol Lagi.

Pembaruan 1: Deteksi otomatis tanpa menyegarkan halaman:

<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>
Jenei Tamás
sumber
100%! Bagaimana jika tautan gambar Anda diblokir oleh proxy / firewall atau server gambar tidak merespons? Anda masih memiliki jaringan yang berfungsi :)
Sen Jacob
Ini akan memuat setiap gambar sekali lagi dari server, menghancurkan cache (sengaja). Jadi hanya untuk memeriksa, Anda (setidaknya) menggandakan bandwidth untuk semua gambar Anda. Selain itu, ia hanya memeriksa jika gambar ada di server, bukan apakah gambar itu dimuat di suatu tempat tertentu. Juga tidak ada cara untuk mengetahui kapan setiap gambar dimuat.
Marius Balčytis
3

Setelah membaca solusi menarik di halaman ini, saya membuat solusi yang mudah digunakan yang sangat dipengaruhi oleh pos SLaks dan Noyo yang tampaknya bekerja pada versi terbaru (saat penulisan) Chrome, IE, Firefox, Safari, dan Opera (semua di Windows). Juga, ini bekerja pada emulator iPhone / iPad yang saya gunakan.

Salah satu perbedaan utama antara solusi ini dan posting SLaks dan Noyo adalah bahwa solusi ini terutama memeriksa properti naturalWidth dan naturalHeight. Saya telah menemukan bahwa dalam versi browser saat ini, kedua properti tersebut tampaknya memberikan hasil yang paling bermanfaat dan konsisten.

Kode ini mengembalikan TRUE ketika gambar telah dimuat penuh DAN berhasil. Ini mengembalikan FALSE ketika gambar belum dimuat penuh ATAU gagal memuat.

Satu hal yang perlu Anda perhatikan adalah bahwa fungsi ini juga akan mengembalikan SALAH jika gambar tersebut adalah gambar 0x0 piksel. Tapi gambar-gambar itu sangat jarang, dan saya tidak bisa memikirkan kasus yang sangat berguna di mana Anda ingin memeriksa untuk melihat apakah gambar 0x0 piksel telah dimuat :)

Pertama kita lampirkan fungsi baru yang disebut "isLoaded" ke prototipe HTMLImageElement, sehingga fungsi tersebut dapat digunakan pada elemen gambar apa pun.

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;

};

Kemudian, setiap saat kita perlu memeriksa status pemuatan gambar, kita cukup memanggil fungsi "isLoaded".

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

Per komentar giorgian tentang pos SLaks dan Noyo, solusi ini mungkin hanya dapat digunakan sebagai pemeriksaan satu kali pada Safari Mobile jika Anda berencana mengubah atribut SRC. Tetapi Anda dapat mengatasinya dengan membuat elemen gambar dengan atribut SRC baru alih-alih mengubah atribut SRC pada elemen gambar yang ada.

data-dan
sumber
2

Ini adalah bagaimana saya membuatnya bekerja lintas browser menggunakan kombinasi metode di atas (saya juga perlu memasukkan gambar secara dinamis ke dalam 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');
    }
});

Catatan: Anda harus menyediakan status boolean yang valid untuk variabel isIE.

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

// Atau Sebagai Plugin

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

// $(".myImage").isLoaded() 
KhaledDev
sumber
1

Seperti yang saya mengerti properti .complete adalah non-standar. Ini mungkin tidak universal ... Saya melihat itu tampaknya bekerja secara berbeda di Firefox ayat IE. Saya memuat sejumlah gambar dalam javascript kemudian memeriksa apakah sudah selesai. Di Firefox, ini sepertinya bekerja dengan baik. Di IE, itu bukan karena gambar tampak memuat di utas lainnya. Ini hanya berfungsi jika saya menunda antara tugas saya ke image.src dan ketika saya memeriksa properti image.complete.

Menggunakan image.onload dan image.onerror juga tidak berfungsi untuk saya, karena saya perlu memberikan parameter untuk mengetahui gambar yang saya bicarakan ketika fungsi dipanggil. Cara apa pun yang tampaknya gagal karena sebenarnya tampaknya melewati fungsi yang sama, bukan contoh berbeda dari fungsi yang sama. Jadi nilai yang saya berikan untuk mengidentifikasi gambar selalu berakhir dengan nilai terakhir dalam loop. Saya tidak bisa memikirkan jalan keluar masalah ini.

Di Safari dan Chrome, saya melihat image.complete benar dan naturalWidth ditetapkan bahkan ketika konsol kesalahan menunjukkan 404 untuk gambar itu ... dan saya sengaja menghapus gambar itu untuk menguji ini. Tetapi hal di atas berfungsi baik untuk Firefox dan IE.

pengguna1018645
sumber
Hmm, itu menarik. Apakah keberatan memposting contoh kode jadi saya ingin mencoba beberapa hal?
Xavi
1

Cuplikan kode ini membantu saya memperbaiki masalah cache browser:

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

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

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

Saat cache browser dinonaktifkan, hanya kode ini yang tidak berfungsi:

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

untuk membuatnya berfungsi, Anda harus menambahkan:

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

Menggunakan JavaScriptkode ini Anda dapat memeriksa gambar berhasil dimuat atau tidak.

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

Coba ini

Ajay Gupta
sumber
0

Saya punya banyak masalah dengan pemuatan lengkap gambar dan EventListener.

Apa pun yang saya coba, hasilnya tidak dapat diandalkan.

Tetapi kemudian saya menemukan solusinya. Secara teknis ini tidak bagus, tapi sekarang saya tidak pernah mengalami gagal memuat gambar.

Apa yang saya lakukan:

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

Alih-alih memuat gambar satu kali, saya hanya memuatnya langsung kedua kalinya setelah pertama kali dan keduanya berjalan melalui eventhandler.

Semua sakit kepala saya hilang!


By the way: Kalian dari stackoverflow membantu saya sudah lebih dari seratus kali. Untuk ini, terima kasih banyak!

Scoobeedo Cool
sumber
0

Yang ini bekerja dengan baik untuk saya :)

$('.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');
});
Kannan Uthaman
sumber