298 votes

Callback jQuery sur le chargement de l'image (même si l'image est en cache)

Je veux le faire :

$("img").bind('load', function() {
  // do stuff
});

Mais l'événement load ne se déclenche pas lorsque l'image est chargée depuis le cache. La documentation de jQuery suggérer un plugin pour résoudre ce problème, mais ça ne marche pas

13 votes

Depuis votre question, les choses ont changé. Le plugin cassé a été déplacé vers un gist et plus tard vers un repo avec un fichier Petit plugin fonctionnel jQuery.imagesLoaded . Ils réparent tous les les petites bizarreries du navigateur .

0 votes

La bibliothèque JQuery mentionnée ci-dessus a bien fonctionné pour moi. Merci !

0 votes

Merci pour le plugin, il a bien fonctionné.

584voto

Nick Craver Points 313913

Si le src est déjà défini, alors l'événement se déclenche dans le cas de la mise en cache, avant même que le gestionnaire d'événement ne soit lié. Pour résoudre ce problème, vous pouvez boucler la vérification et le déclenchement de l'événement en fonction des éléments suivants .complete comme ceci :

$("img").one("load", function() {
  // do stuff
}).each(function() {
  if(this.complete) {
      $(this).load(); // For jQuery < 3.0 
      // $(this).trigger('load'); // For jQuery >= 3.0 
  }
});

Notez le changement de .bind() a .one() pour que le gestionnaire d'événement ne soit pas exécuté deux fois.

8 votes

Votre solution a fonctionné parfaitement pour moi, mais je veux comprendre quelque chose, quand ce code "if(this.complete)" sera exécuté, après le chargement du contenu de l'image ou avant ? parce que comme je peux comprendre de ce .each que vous bouclez sur tous les $("img") et peut-être le contenu de l'image est vide et le chargement ne se produira pas. hmmmm, je pense que j'ai quelque chose qui manque, il serait bien si vous pouvez décrire ce qui se passe pour mieux le comprendre. merci.

37 votes

Depuis votre réponse, les choses ont changé. Il existe maintenant un Petit plugin fonctionnel jQuery.imagesLoaded . Ils réparent tous les les petites bizarreries du navigateur .

0 votes

Fonctionne parfaitement avec jQuery. Quelle est l'alternative de one y complete dans Prototype (la bibliothèque) ?

53voto

Gus Points 3577

Puis-je vous suggérer de le recharger dans un objet image non DOM ? S'il est mis en cache, cela ne prendra pas de temps du tout, et le onload se déclenchera quand même. Si elle n'est pas mise en cache, le onload se déclenchera au moment du chargement de l'image, ce qui devrait correspondre à la fin du chargement de la version DOM de l'image.

Javascript :

$(document).ready(function() {
    var tmpImg = new Image() ;
    tmpImg.src = $('#img').attr('src') ;
    tmpImg.onload = function() {
        // Run onload code.
    } ;
}) ;

Mise à jour (pour gérer les images multiples et avec une pièce jointe onload correctement ordonnée) :

$(document).ready(function() {
    var imageLoaded = function() {
        // Run onload code.
    }
    $('#img').each(function() {
        var tmpImg = new Image() ;
        tmpImg.onload = imageLoaded ;
        tmpImg.src = $(this).attr('src') ;
    }) ;
}) ;

1 votes

Vous devez essayer d'attacher le load manipulateur antes de c'est ajouté, aussi cela ne fonctionnera que pour une image, le code du PO fonctionne pour plusieurs :)

0 votes

Merci, j'ai ajouté une version mise à jour qui, je l'espère, résout ces deux problèmes.

0 votes

#img est un ID et non un sélecteur d'élément :) Voir aussi this.src fonctionne, pas besoin d'utiliser jQuery là où il n'est pas nécessaire :) Mais créer une autre image semble exagéré dans les deux cas.

41voto

guari Points 916

Ma solution simple, elle ne nécessite aucun plugin externe et devrait suffire pour les cas courants :

/**
 * Trigger a callback when the selected images are loaded:
 * @param {String} selector
 * @param {Function} callback
  */
var onImgLoad = function(selector, callback){
    $(selector).each(function(){
        if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
            callback.apply(this);
        }
        else {
            $(this).on('load', function(){
                callback.apply(this);
            });
        }
    });
};

Utilisez-le comme ceci :

onImgLoad('img', function(){
    // do stuff
});

par exemple, pour faire apparaître vos images en fondu sur la charge, vous pouvez le faire :

$('img').hide();
onImgLoad('img', function(){
    $(this).fadeIn(700);
});

Ou comme alternative, si vous préférez une approche de type plugin jquery :

/**
 * Trigger a callback when 'this' image is loaded:
 * @param {Function} callback
 */
(function($){
    $.fn.imgLoad = function(callback) {
        return this.each(function() {
            if (callback) {
                if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
                    callback.apply(this);
                }
                else {
                    $(this).on('load', function(){
                        callback.apply(this);
                    });
                }
            }
        });
    };
})(jQuery);

et l'utiliser de cette manière :

$('img').imgLoad(function(){
    // do stuff
});

par exemple :

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});

0 votes

Urm et si mes images ont une taille définie avec css ?

0 votes

Définir width , max-height et laisser height:auto Pour une solution plus robuste, j'utiliserais un plugin tel que ImagesLoaded

0 votes

Ai-je raison de dire que l'emballage selector en $() - c'est-à-dire, $(selector).each(...) - est redondant étant donné que vous avez déjà appelé la fonction avec un objet jQuery -. onImgLoad($('img'),...) ?

23voto

Björn Points 15485

Faut-il vraiment le faire avec jQuery ? Vous pouvez joindre le onload directement sur votre image ;

<img src="/path/to/image.jpg" onload="doStuff(this);" />

Il se déclenchera chaque fois que l'image sera chargée, à partir du cache ou non.

5 votes

Il est plus propre sans javascript en ligne

1 votes

Bonjour, Bjorn, est-ce que le onload se déclenche lorsque l'image est chargée une deuxième fois à partir du cache ?

1 votes

@Cupidvogel non ça ne le sera pas.

13voto

Sammaye Points 21778

J'ai eu ce problème moi-même, j'ai cherché partout une solution qui n'implique pas de tuer mon cache ou de télécharger un plugin.

Je n'ai pas vu ce fil de discussion immédiatement et j'ai donc trouvé quelque chose d'autre à la place qui est une solution intéressante et (je pense) digne d'être postée ici :

$('.image').load(function(){
    // stuff
}).attr('src', 'new_src');

En fait, j'ai eu cette idée dans les commentaires ici : http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

Je n'ai aucune idée de la raison pour laquelle cela fonctionne, mais je l'ai testé sur IE7 et là où cela ne fonctionnait pas auparavant, cela fonctionne maintenant.

J'espère que cela vous aidera,

Modifier

La réponse acceptée explique en fait pourquoi :

Si le src est déjà défini, l'événement est déclenché dans le cache avant que le gestionnaire d'événement ne soit lié.

4 votes

Je l'ai testé dans de nombreux navigateurs et je n'ai constaté aucun échec. J'ai utilisé $image.load(function(){ something(); }).attr('src', $image.attr('src')); pour rétablir la source originale.

0 votes

J'ai constaté que cette approche ne fonctionne pas sous iOS, du moins pour Safari/601.1 et Safari/602.1.

0 votes

Ce serait génial de savoir pourquoi, avec quel navigateur ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X