Il modo ufficiale per chiedere a jQuery di attendere il caricamento di tutte le immagini prima di eseguire qualcosa


641

In jQuery quando esegui questa operazione:

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

Attende il caricamento del DOM ed esegue il codice. Se tutte le immagini non vengono caricate, esegue comunque il codice. Questo è ovviamente ciò che vogliamo se inizializziamo elementi DOM come mostrare o nascondere elementi o allegare eventi.

Diciamo però che voglio un po 'di animazione e non voglio che funzioni fino a quando non vengono caricate tutte le immagini. Esiste un modo ufficiale in jQuery per farlo?

Il modo migliore che ho è di usare <body onload="finished()">, ma non voglio davvero farlo a meno che non sia necessario.

Nota: esiste un bug in jQuery 1.3.1 in Internet Explorer che in realtà attende il caricamento di tutte le immagini prima di eseguire il codice all'interno $function() { }. Quindi se stai usando quella piattaforma otterrai il comportamento che sto cercando invece del comportamento corretto descritto sopra.


3
non $("img").load()funziona?
Lucas,

1
Penso che valga la pena ricordare che se si impostano gli attributi delle dimensioni, è possibile eseguire in modo sicuro del codice in funzione ready che si basa su tali dimensioni. Con php puoi acquisirli con php.net/manual/en/function.getimagesize.php al momento del caricamento per memorizzarli in db o prima dell'output sul browser.
Alqin,

se vuoi che qualcosa stia facendo un lavoro incredibile, dai un'occhiata alla libreria javascript caricata con immagini estremamente buona e popolare menzionata in questa risposta sotto stackoverflow.com/a/26458347/759452
Adrien Be

"Qui sono venuto a trovare qualsiasi cosa tranne un modo ufficiale."
Léon Pelletier,

Risposte:


1035

Con jQuery, si utilizza $(document).ready()per eseguire qualcosa quando viene caricato il DOM e $(window).on("load", handler)per eseguire qualcosa anche quando vengono caricate tutte le altre cose, come le immagini.

La differenza può essere vista nel seguente file HTML completo, a condizione che tu abbia un jollyrogerfile JPEG (o altri adatti):

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

Con ciò, la finestra di avviso appare prima che le immagini vengano caricate, perché il DOM è pronto a quel punto. Se poi cambi:

$(document).ready(function() {

in:

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

quindi la finestra di avviso non viene visualizzata fino a dopo il caricamento delle immagini.

Quindi, per attendere che l'intera pagina sia pronta, è possibile utilizzare qualcosa del tipo:

$(window).on("load", function() {
    // weave your magic here.
});

32
colpisce la fronte +1 totalmente dimenticato. $ (finestra) .load () non si attiva fino a quando le immagini non vengono eseguite.
Paolo Bergantino,

10
Ho fatto lo stesso. Persino, leggi una risposta senza sapere che ero io e ancora non capisco.
Rimian,

24
Solo una nota: questo non sembra funzionare con Chromium (e presumo che Chrome). L'evento $ (finestra) .ready sembra attivarsi come $ (documento). Già - prima che le immagini vengano completate.
Nathan Crause

24
ma è $ (finestra) .load (funzione ())
TJ-

3
@KyorCode Sei sicuro che non sia solo perché le immagini in IE sono state memorizzate nella cache? Se ciò accade, non genereranno affatto un evento "load". Questo articolo aiuta a risolvere questo problema.
Jamie Barker,

157

Ho scritto un plug-in in grado di attivare i callback quando le immagini sono state caricate in elementi o attivate una volta per ogni immagine caricata.

È simile $(window).load(function() { .. }), tranne per il fatto che consente di definire qualsiasi selettore da controllare. Se vuoi solo sapere quando #contentsono state caricate tutte le immagini (ad esempio), questo è il plug-in che fa per te.

Supporta anche il caricamento delle immagini si fa riferimento nel CSS, come ad esempio background-image, list-style-image, etc.

waitForImages plugin jQuery

Esempio di utilizzo

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

Esempio su jsFiddle .

Più documentazione è disponibile sulla pagina GitHub.


1
Grazie!! $ .load () non funzionava per me, ma questo funziona perfettamente.
Fraxtil,

Uso la versione 22.0.1229.94 di Chrome e questo plug-in e ho provato a leggere gli offset dalle immagini caricate all'interno di waitFormImages: ('img selector').each(function(index) { var offset = $(this).offset(); ...});tuttavia offset.top è ancora zero. Perché?
basZero

1
@basZero Difficile dirlo senza più contesto. Si prega di sollevare un problema nella pagina Problemi .
alex,

Non funziona per me quando le immagini vengono tranciate. Any1 ha una soluzione alternativa per questo?
Mandeep Jain,

2
È sostanzialmente analogo alle immagini caricate ma funziona anche con gli srcset. Esattamente quello che stavo cercando! Ottimo plugin!
Fabian Schöner,

48

$(window).load()funzionerà solo al primo caricamento della pagina. Se stai facendo cose dinamiche (esempio: pulsante di clic, attendi il caricamento di alcune nuove immagini), questo non funzionerà. Per riuscirci, puoi usare il mio plugin:

dimostrazione

Scarica

/**
 *  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);

nel caso in cui qualcuno abbia bisogno di un esempio di utilizzo del plugin BatchImagesLoad
Jonathan Marzullo,

1
Non intendo mancare di rispetto, ma non si può fare affidamento "solo" sulla propria parola per quanto riguarda l'affidabilità del proprio plugin. Come indicato nella Yevgeniy Afanasyevrisposta , imagesLoaded fa un lavoro molto migliore in questo e copre il caso d'uso che hai citato insieme a molti altri casi angolari (vedi i problemi risolti di github) .
Adrien, il

19

Per coloro che desiderano ricevere una notifica del completamento del download di una singola immagine che viene richiesta dopo gli $(window).loadincendi, è possibile utilizzare l' loadevento dell'elemento immagine .

per esempio:

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

13

Nessuna delle risposte finora ha dato quella che sembra essere la soluzione più semplice.

$('#image_id').load(
  function () {
    //code here
});

La cosa bella di questo è che puoi farlo scattare per le singole immagini non appena vengono caricate.
Top Cat

6

Consiglierei di usare la imagesLoaded.jslibreria javascript.

Perché non usare jQuery $(window).load()?

Come risposto su /programming/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

È una questione di portata. imagesLoaded ti consente di scegliere come target un set di immagini, mentre $(window).load()tutti gli asset sono inclusi, inclusi immagini, oggetti, file .js e .css e persino iframe. Molto probabilmente, imagesLoaded si attiverà prima che $(window).load()perché si rivolge a un set di risorse più piccolo.

Altri buoni motivi per usare le immagini caricate

  • ufficialmente supportato da IE8 +
  • licenza: licenza MIT
  • dipendenze: nessuna
  • peso (minimizzato e decompresso): minimizzato 7kb (leggero!)
  • download builder (aiuta a ridurre il peso): non è necessario, già piccolo
  • su Github: SÌ
  • community e collaboratori: piuttosto grandi, oltre 4000 membri, anche se solo 13 collaboratori
  • storia e contributi: stabile come relativamente vecchio (dal 2010) ma progetto ancora attivo

risorse


4

Con jQuery vengo con questo ...

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


Ho scoperto che questo non funzionerà correttamente se il browser restituisce una risposta 304 non non modificata per l'immagine, il che significa che l'immagine è memorizzata nella cache.
JohnyFree,

1

Usa immagini caricate PACKAGED v3.1.8 (6,8 Kb se ridotto a icona). È relativamente vecchio (dal 2010) ma è ancora un progetto attivo.

Puoi trovarlo su github: https://github.com/desandro/imagesloaded

Il loro sito ufficiale: http://imagesloaded.desandro.com/

Perché è meglio dell'uso:

$(window).load() 

Perché potresti voler caricare le immagini in modo dinamico, in questo modo: jsfiddle

$('#button').click(function(){
    $('#image').attr('src', '...');
});

1
In realtà, le immagini caricate non supportano la modifica del valore dell'attributo src nel browser. È necessario creare un nuovo elemento immagine ogni volta. Provalo su Firefox e vedrai apparire il problema.
Adrien, il

Bene, ho ancora testato su Google Chrome e IE-11. Funzionava. Grazie.
Yevgeniy Afanasyev,

Ho aggiunto questo problema tra browser nella mia domanda stackoverflow.com/q/26927575 nel punto "Cosa non puoi fare con le immagini caricate", vedi le immagini Problema rilevante caricato su Github github.com/desandro/imagesloaded/issues/121
Adrien Sii il

1

In questo modo è possibile eseguire un'azione quando vengono caricate tutte le immagini all'interno del corpo o di qualsiasi altro contenitore (che dipende dalla selezione). PURE JQUERY, nessun plug-in necessario.

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

0

La mia soluzione è simile al molokoloco . Scritto come funzione 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);
};

esempio:

<div>
    <img src="img1.png"/>
    <img src="img2.png"/>
</div>
<script>
    $('div').waitForImages(function () {
        console.log('img loaded');
    });
</script>
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.