web-dev-qa-db-fra.com

Manière officielle de demander à jQuery d'attendre le chargement de toutes les images avant d'exécuter quelque chose

Dans jQuery quand vous faites ceci:

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

Il attend que le DOM se charge et exécute votre code. Si toutes les images ne sont pas chargées, le code est toujours exécuté. C’est évidemment ce que nous voulons si nous initialisons des éléments du DOM tels que l’affichage ou le masquage d’éléments ou l’attachement d’événements.

Disons cependant que je veux une animation et que je ne veux pas qu'elle s'exécute tant que toutes les images ne sont pas chargées. Existe-t-il un moyen officiel dans jQuery de le faire?

Le meilleur moyen que j'ai est d'utiliser <body onload="finished()">, mais je ne veux pas vraiment le faire sauf si je dois le faire.

Remarque: Il existe un bogue dans jQuery 1.3.1 dans Internet Explorer qui attend le chargement de toutes les images avant d'exécuter du code dans $function() { }. Donc, si vous utilisez cette plate-forme, vous obtiendrez le comportement que je recherche au lieu du comportement correct décrit ci-dessus.

625
Simon_Weaver

Avec jQuery, vous utilisez $(document).ready() pour exécuter quelque chose lorsque le DOM est chargé et $(window).on("load", handler) pour exécuter quelque chose lorsque tous les autres éléments sont également chargés, tels que les images.

La différence peut être vue dans le fichier HTML complet suivant, à condition que vous ayez un jollyroger JPEG (ou d’autres fichiers appropriés):

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

Avec cela, la boîte d'alerte apparaît avant le chargement des images, car le DOM est prêt à ce stade. Si vous changez alors:

$(document).ready(function() {

dans:

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

alors la boîte d'alerte n'apparaît que jusqu'à after les images sont chargées.

Par conséquent, pour attendre que la page entière soit prête, vous pouvez utiliser quelque chose comme:

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

J'ai écrit un plugin capable de déclencher des rappels lorsque des images ont été chargées dans des éléments ou de se déclencher une fois par image chargée.

Il est similaire à $(window).load(function() { .. }), sauf qu'il vous permet de définir n'importe quel sélecteur à vérifier. Si vous voulez seulement savoir quand toutes les images de #content (par exemple) ont été chargées, c'est le plugin qui vous convient.

Il prend également en charge le chargement des images référencées dans le CSS, telles que background-image, list-style-image, etc.

waitForImages jQuery plugin

Exemple d'utilisation

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

Exemple sur jsFiddle .

Plus de documentation est disponible sur la page GitHub.

156
alex

$(window).load() ne fonctionnera que la première fois que la page est chargée. Si vous faites des choses dynamiques (exemple: cliquez sur le bouton, attendez le chargement de nouvelles images), cela ne fonctionnera pas. Pour cela, vous pouvez utiliser mon plugin:

démo

Télécharger

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

Pour ceux qui souhaitent être informés de l'achèvement du téléchargement d'une seule image demandée après le déclenchement de $(window).load, vous pouvez utiliser l'événement load de l'élément d'image.

par exemple.:

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

Aucune des réponses à ce jour n'a donné ce qui semble être la solution la plus simple.

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

Je recommanderais d'utiliser imagesLoaded.js librairie javascript.

Pourquoi ne pas utiliser $(window).load() de jQuery?

Comme indiqué sur https://stackoverflow.com/questions/26927575/why-use-imagesloaded-javascript-library-versus-jquerys-window-load/26929951

C'est une question de portée. imagesLoaded vous permet de cibler un ensemble d'images, alors que $(window).load() cible tous les actifs , y compris toutes les images, objets, fichiers .js et .css, et même des iframes. Très probablement, imagesLoaded se déclenchera plus tôt que $(window).load(), car il cible un plus petit ensemble d’actifs.

Autres bonnes raisons d'utiliser imagesloaded

  • officiellement supporté par IE8 +
  • licence: MIT Licence
  • dépendances: aucune
  • poids (minifié et gzippé): 7kb minifié (léger!)
  • téléchargement constructeur (aide à réduire le poids): pas besoin, déjà minuscule
  • sur Github: OUI
  • communauté et contributeurs: assez gros, plus de 4000 membres, bien que seulement 13 contributeurs
  • historique et contributions: projet relativement stable (depuis 2010) mais toujours actif

Ressources

6
Adrien Be

Avec jQuery je viens avec ça ...

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

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

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

Démo: http://jsfiddle.net/molokoloco/NWjDb/

4
molokoloco

De cette façon, vous pouvez exécuter une action lorsque toutes les images du corps ou de tout autre conteneur (cela dépend de votre sélection) sont chargées. PURE JQUERY, aucun plug-in nécessaire.

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

Utilisez imagesLoaded PACKAGED v3.1.8 (6.8 Kb lorsqu'il est réduit). C'est un projet relativement ancien (depuis 2010) mais toujours actif.

Vous pouvez le trouver sur github: https://github.com/desandro/imagesloaded

Leur site officiel: http://imagesloaded.desandro.com/

Pourquoi c'est mieux que d'utiliser:

$(window).load() 

Parce que vous voudrez peut-être charger des images dynamiquement, comme ceci: jsfiddle

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

Ma solution est similaire à molokoloco . Écrit en tant que fonction 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);
};

exemple:

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