Cara resmi untuk meminta jQuery menunggu semua gambar dimuat sebelum menjalankan sesuatu

641

Di jQuery saat Anda melakukan ini:

$(function() {
   alert("DOM is loaded, but images not necessarily all loaded");
});

Itu menunggu DOM untuk memuat dan mengeksekusi kode Anda. Jika semua gambar tidak dimuat maka masih menjalankan kode. Ini jelas yang kita inginkan jika kita menginisialisasi hal-hal DOM seperti menunjukkan atau menyembunyikan elemen atau melampirkan acara.

Katakan saja saya ingin animasi dan saya tidak ingin itu berjalan sampai semua gambar dimuat. Apakah ada cara resmi di jQuery untuk melakukan ini?

Cara terbaik yang saya miliki adalah menggunakan <body onload="finished()">, tetapi saya tidak benar-benar ingin melakukan itu kecuali saya harus melakukannya.

Catatan: Ada bug di jQuery 1.3.1 di Internet Explorer yang sebenarnya menunggu semua gambar dimuat sebelum menjalankan kode di dalamnya $function() { }. Jadi, jika Anda menggunakan platform itu, Anda akan mendapatkan perilaku yang saya cari alih-alih perilaku yang benar yang dijelaskan di atas.

Simon_Weaver
sumber
3
tidak $("img").load()bekerja?
Lucas
1
Saya pikir mungkin layak disebutkan bahwa jika Anda mengatur atribut dimensi, Anda dapat dengan aman menjalankan beberapa kode dalam fungsi siap pakai yang mengandalkan dimensi tersebut. Dengan php Anda dapat mengambilnya dengan php.net/manual/en/function.getimagesize.php saat diunggah untuk menyimpannya di db atau sebelum di-output ke browser.
Alqin
jika Anda menginginkan sesuatu melakukan pekerjaan yang luar biasa, maka periksa perpustakaan javascript imagesloaded yang sangat bagus & populer yang disebutkan dalam jawaban di bawah ini stackoverflow.com/a/26458347/759452
Adrien Be
"Di sini aku datang untuk menemukan apa pun kecuali cara resmi."
Léon Pelletier

Jawaban:

1035

Dengan jQuery, Anda menggunakan $(document).ready()untuk mengeksekusi sesuatu ketika DOM dimuat dan $(window).on("load", handler)untuk mengeksekusi sesuatu ketika semua hal lainnya dimuat juga, seperti gambar.

Perbedaannya dapat dilihat pada file HTML lengkap berikut, asalkan Anda memiliki jollyrogerfile JPEG (atau yang sesuai lainnya):

<html>
    <head>
        <script src="jquery-1.7.1.js"></script>
        <script type="text/javascript">
            $(document).ready(function() {
                alert ("done");
            });
        </script>
    </head><body>
        Hello
        <img src="jollyroger00.jpg">
        <img src="jollyroger01.jpg">
        // : 100 copies of this
        <img src="jollyroger99.jpg">
    </body>
</html>

Dengan itu, kotak peringatan muncul sebelum gambar dimuat, karena DOM siap pada saat itu. Jika kemudian Anda mengubah:

$(document).ready(function() {

ke:

$(window).on("load", function() {

maka kotak peringatan tidak muncul sampai setelah gambar dimuat.

Karenanya, untuk menunggu hingga seluruh halaman siap, Anda dapat menggunakan sesuatu seperti:

$(window).on("load", function() {
    // weave your magic here.
});
paxdiablo
sumber
32
memukul dahi +1 benar-benar lupa itu. $ (jendela) .load () tidak akan aktif sampai gambar selesai.
Paolo Bergantino
10
Saya sudah melakukan hal yang sama. Bahkan, baca jawaban yang tidak tahu itu aku dan masih belum memahaminya.
Rimian
24
Hanya sebuah catatan - ini sepertinya tidak berfungsi di bawah Chromium (dan saya kira Chrome). Acara $ (window) .ready tampaknya memecat sama dengan $ (document) .ready - sebelum gambar selesai.
Nathan Crause
24
tapi $ (window) .load (function ())
TJ-
3
@KyorCode Apakah Anda yakin itu bukan hanya karena gambar di IE di-cache? Jika itu terjadi, mereka tidak akan memecat acara "memuat" sama sekali. Artikel ini membantu untuk mengatasi masalah ini.
Jamie Barker
157

Saya menulis sebuah plugin yang dapat memecat panggilan balik ketika gambar telah dimuat dalam elemen, atau memecat sekali per gambar dimuat.

Ini mirip dengan $(window).load(function() { .. }), kecuali itu memungkinkan Anda menentukan pemilih untuk memeriksa. Jika Anda hanya ingin tahu kapan semua gambar di #content(misalnya) telah dimuat, ini adalah plugin untuk Anda.

Ini juga mendukung pemuatan gambar dirujuk dalam CSS, seperti background-image, list-style-image, dll

plugin waitForImages jQuery

Contoh Penggunaan

$('selector').waitForImages(function() {
    alert('All images are loaded.');
});

Contoh di jsFiddle .

Dokumentasi lebih lanjut tersedia di halaman GitHub.

alex
sumber
1
Terima kasih!! $ .load () tidak berfungsi untuk saya, tetapi ini berhasil dengan sempurna.
Fraxtil
Saya menggunakan Chrome Versi 22.0.1229.94 dan plugin ini, dan saya mencoba membaca offset dari gambar yang dimuat di dalam waitFormImages:, ('img selector').each(function(index) { var offset = $(this).offset(); ...});bagaimanapun, offset.top masih nol. Mengapa?
basZero
1
@ basZero Sulit diceritakan tanpa lebih banyak konteks. Harap sampaikan masalah di halaman Masalah .
alex
Ini tidak berfungsi untuk saya ketika gambar di-cahced. Apakah ada yang punya solusi untuk ini?
Mandeep Jain
2
Pada dasarnya analog dengan imagesLoaded tetapi berfungsi dengan srcsets juga. Persis apa yang saya cari! Plugin hebat!
Fabian Schöner
48

$(window).load()hanya akan berfungsi saat pertama kali laman dimuat. Jika Anda melakukan hal-hal dinamis (contoh: tombol klik, tunggu beberapa gambar baru dimuat), ini tidak akan berfungsi. Untuk mencapai itu, Anda dapat menggunakan plugin saya:

Demo

Unduh

/**
 *  Plugin which is applied on a list of img objects and calls
 *  the specified callback function, only when all of them are loaded (or errored).
 *  @author:  H. Yankov (hristo.yankov at gmail dot com)
 *  @version: 1.0.0 (Feb/22/2010)
 *  http://yankov.us
 */

(function($) {
$.fn.batchImageLoad = function(options) {
    var images = $(this);
    var originalTotalImagesCount = images.size();
    var totalImagesCount = originalTotalImagesCount;
    var elementsLoaded = 0;

    // Init
    $.fn.batchImageLoad.defaults = {
        loadingCompleteCallback: null, 
        imageLoadedCallback: null
    }
    var opts = $.extend({}, $.fn.batchImageLoad.defaults, options);

    // Start
    images.each(function() {
        // The image has already been loaded (cached)
        if ($(this)[0].complete) {
            totalImagesCount--;
            if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);
        // The image is loading, so attach the listener
        } else {
            $(this).load(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // An image has been loaded
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
            $(this).error(function() {
                elementsLoaded++;

                if (opts.imageLoadedCallback) opts.imageLoadedCallback(elementsLoaded, originalTotalImagesCount);

                // The image has errored
                if (elementsLoaded >= totalImagesCount)
                    if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
            });
        }
    });

    // There are no unloaded images
    if (totalImagesCount <= 0)
        if (opts.loadingCompleteCallback) opts.loadingCompleteCallback();
};
})(jQuery);
Roko C. Buljan
sumber
untuk berjaga-jaga jika ada yang membutuhkan contoh penggunaan untuk plugin BatchImagesLoad
Jonathan Marzullo
1
Maksud saya tidak ada rasa hormat tetapi orang tidak bisa mengandalkan "hanya" pada kata Anda mengenai keandalan plugin Anda. Seperti yang disebutkan dalam Yevgeniy Afanasyevjawaban , imagesLoaded melakukan pekerjaan yang jauh lebih baik di sini & mencakup kasus penggunaan yang Anda sebutkan bersama banyak kasus sudut lainnya (lihat masalah github yang diselesaikan) .
Adrien Be
19

Bagi mereka yang ingin diberitahu tentang penyelesaian pengunduhan satu gambar yang diminta setelah $(window).loadkebakaran, Anda dapat menggunakan acara elemen gambar load.

misalnya:

// create a dialog box with an embedded image
var $dialog = $("<div><img src='" + img_url + "' /></div>");

// get the image element (as a jQuery object)
var $imgElement = $dialog.find("img");

// wait for the image to load 
$imgElement.load(function() {
    alert("The image has loaded; width: " + $imgElement.width() + "px");
});
Dan Passaro
sumber
13

Sejauh ini tidak ada jawaban yang memberikan solusi paling sederhana.

$('#image_id').load(
  function () {
    //code here
});
Coz
sumber
Apa yang baik tentang ini adalah Anda bisa memicu gambar individual segera setelah mereka memuat.
Top Cat
6

Saya akan merekomendasikan menggunakan imagesLoaded.jsperpustakaan javascript.

Mengapa tidak menggunakan jQuery $(window).load()?

Seperti yang dijelaskan pada /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

Ini masalah ruang lingkup. imagesLoaded memungkinkan Anda menargetkan sekumpulan gambar, sedangkan $(window).load()menargetkan semua aset - termasuk semua gambar, objek, file .js dan .css, dan bahkan iframe. Kemungkinan besar, imagesLoaded akan memicu lebih cepat daripada $(window).load()karena menargetkan sekelompok aset yang lebih kecil.

Alasan bagus lainnya untuk menggunakan imagesloaded

  • secara resmi didukung oleh IE8 +
  • lisensi: Lisensi MIT
  • dependensi: tidak ada
  • berat (minified & gzipped): 7kb minified (ringan!)
  • download builder (membantu mengurangi berat): tidak perlu, sudah kecil
  • pada Github: YA
  • komunitas & kontributor: cukup besar, 4000+ anggota, meskipun hanya 13 kontributor
  • sejarah & kontribusi: stabil sejak relatif lama (sejak 2010) tetapi proyek masih aktif

Sumber daya

Adrien Be
sumber
4

Dengan jQuery saya datang dengan ini ...

$(function() {
    var $img = $('img'),
        totalImg = $img.length;

    var waitImgDone = function() {
        totalImg--;
        if (!totalImg) alert("Images loaded!");
    };

    $('img').each(function() {
        $(this)
            .load(waitImgDone)
            .error(waitImgDone);
    });
});

Demo: http://jsfiddle.net/molokoloco/NWjDb/

molokoloco
sumber
Saya menemukan bahwa ini tidak akan berfungsi dengan baik jika browser mengembalikan 304 Not Mofified response for image yang berarti bahwa gambar di-cache.
JohnyFree
1

Gunakan imagesLoaded PACKAGED v3.1.8 (6.8 Kb saat diperkecil). Ini relatif lama (sejak 2010) tetapi proyek masih aktif.

Anda dapat menemukannya di github: https://github.com/desandro/imagesloaded

Situs resmi mereka: http://imagesloaded.desandro.com/

Mengapa lebih baik daripada menggunakan:

$(window).load() 

Karena Anda mungkin ingin memuat gambar secara dinamis, seperti ini: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});
Yevgeniy Afanasyev
sumber
1
Sebenarnya, imagesloaded tidak mendukung perubahan browser lintas nilai atribut src. Anda harus membuat elemen gambar baru setiap kali. Cobalah di Firefox dan Anda akan melihat masalah muncul.
Adrien Be
Poin baiknya, saya baru menguji di Google chrome dan IE-11. Itu berhasil. Terima kasih.
Yevgeniy Afanasyev
Saya memang menambahkan masalah lintas-peramban ini dalam pertanyaan saya stackoverflow.com/q/26927575 pada titik "Apa yang tidak dapat Anda lakukan dengan imagesloaded", lihat imagesLoaded relevan masalah pada Github github.com/desandro/imagesloaded/issues/121
Adrien Jadilah
1

Dengan cara ini Anda dapat melakukan suatu tindakan ketika semua gambar di dalam tubuh atau wadah lain (yang tergantung pilihan Anda) dimuat. MURNI JQUERY, tidak perlu pluggin.

var counter = 0;
var size = $('img').length;

$("img").load(function() { // many or just one image(w) inside body or any other container
    counter += 1;
    counter === size && $('body').css('background-color', '#fffaaa'); // any action
}).each(function() {
  this.complete && $(this).load();        
});
Mario Medrano
sumber
0

Solusi saya mirip dengan molokoloco . Ditulis sebagai fungsi jQuery:

$.fn.waitForImages = function (callback) {
    var $img = $('img', this),
        totalImg = $img.length;

    var waitImgLoad = function () {
        totalImg--;
        if (!totalImg) {
            callback();
        }
    };

    $img.each(function () {
        if (this.complete) { 
            waitImgLoad();
        }
    })

    $img.load(waitImgLoad)
        .error(waitImgLoad);
};

contoh:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
Mariusz Charczuk
sumber