web-dev-qa-db-fra.com

Vérifier si une image est chargée (pas d'erreur) avec jQuery

J'utilise JavaScript avec la bibliothèque jQuery pour manipuler les vignettes d'images contenues dans une liste non ordonnée. Lorsque l'image est chargée, elle fait une chose et lorsqu'une erreur survient, elle fait autre chose. J'utilise les méthodes jQuery load() et error() comme événements. Après ces événements, je vérifie l'élément .dom de l'image pour le .complete afin de m'assurer que l'image n'était pas déjà chargée avant que jQuery puisse enregistrer les événements.

Cela fonctionne correctement sauf quand une erreur se produit avant que jQuery puisse enregistrer les événements. La seule solution à laquelle je peux penser est d'utiliser l'attribut img onerror pour stocker un "indicateur" quelque part globalement (ou sur le nœud c'est self) qui dit que cela a échoué afin que jQuery puisse vérifier ce "magasin/nœud" lors de la vérification de .complete.

Quelqu'un a une meilleure solution?

Edit: Points principaux en gras et ajout de détails supplémentaires ci-dessous: Je vérifie si une image est complète (aka chargée) APRÈS avoir ajouté un événement de chargement et d'erreur sur l'image. De cette façon, si l'image a été chargée avant que les événements aient été enregistrés, je le saurai toujours. Si l'image n'est pas chargée après les événements, ceux-ci s'en occuperont le cas échéant. Le problème, c’est que je peux facilement vérifier si une image est déjà chargée, mais je ne peux pas dire si une erreur s’est produite à la place.

207
William

Une autre option consiste à déclencher les événements onload et/ou onerror en créant un élément d'image en mémoire et en définissant son attribut src sur l'attribut original src de l'image d'origine. Voici un exemple de ce que je veux dire:

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

J'espère que cela t'aides!

236
Xavi

Vérifiez les propriétés complete et naturalWidth, dans cet ordre.

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;
}
214
SLaks

D'après ma compréhension de la spécification HTML du W3C pour l'élément img , vous devriez pouvoir le faire en utilisant une combinaison de complete et naturalHeight attributs, comme ceci:

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

D'après les spécifications de l'attribut complete :

L'attribut IDL complete doit renvoyer la valeur true si l'une des conditions suivantes est remplie:

  • L'attribut src est omis.
  • La dernière tâche mise en file d'attente par la source de tâches réseau une fois la ressource extraite a été mise en file d'attente.
  • L'élément img est complètement disponible.
  • L'élément img est cassé.

Sinon, l'attribut doit retourner false.

Donc, essentiellement, complete renvoie true si le chargement de l'image est terminé ou si son chargement a échoué. Puisque nous ne voulons que le cas où l'image est chargée avec succès, nous devons également vérifier l'attribut nauturalHeight :

Les attributs IDL naturalWidth et naturalHeight doivent renvoyer la largeur et la hauteur intrinsèques de l'image, en pixels CSS, si l'image est disponible, sinon 0.

Et available est défini comme suit:

Un img est toujours dans l'un des états suivants:

  • Non disponible - L'agent utilisateur n'a pas obtenu de données d'image.
  • Partiellement disponible - L'agent utilisateur a obtenu une partie des données d'image.
  • Complètement disponible - L'agent utilisateur a obtenu toutes les données d'image et au moins les dimensions de l'image sont disponibles.
  • Cassé - L'agent utilisateur a obtenu toutes les données d'image qu'il peut mais il ne peut même pas décoder l'image suffisamment pour obtenir les dimensions de l'image (par exemple, le l'image est corrompue, le format n'est pas pris en charge ou aucune donnée n'a pu être obtenue).

Lorsqu'un élément img est soit à l'état partiellement disponible, soit à l'état complètement disponible, il est dit disponible.

Donc, si l'image est "cassée" (échec du chargement), alors elle sera dans l'état cassé, pas dans l'état disponible, donc naturalHeight sera 0.

Par conséquent, vérifier imgElement.complete && imgElement.naturalHeight !== 0 devrait nous indiquer si l'image a été chargée avec succès.

Vous pouvez en savoir plus à ce sujet dans la spécification HTML du W3C pour l'élément img ou sur MDN .

50
Ajedi32

J'ai essayé de nombreuses manières différentes et cette méthode est la seule qui a fonctionné pour moi

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

Vous pouvez également ajouter une fonction de rappel déclenchée une fois que toutes les images sont chargées dans le DOM et prêtes. Ceci s'applique également aux images ajoutées dynamiquement. http://jsfiddle.net/kalmarsh80/nrAPk/

19
Kal
12
Josh Harrison

Récupérer des informations à partir d'éléments d'image sur la page
Test de travail sur Chrome et Firefox
Working jsFiddle (ouvrez votre console pour voir le résultat)

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

});

Note: J'ai utilisé jQuery , je pensais que cela pouvait être réalisé en plein javascript

Je trouve de bonnes informations ici OpenClassRoom -> Ceci est un forum français

7
Julha

Détecteur de réseau en temps réel - vérifie l'état du réseau sans actualiser la page: (ce n'est pas jquery, mais testé et 100% fonctionne: (testé sur Firefox v25.0))

Code:

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

si la connexion est perdue, appuyez simplement sur le bouton Encore.

Mise à jour 1: Détecter automatiquement sans actualiser la page:

<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>
3
Jenei Tamás

Voici comment je l'ai fait fonctionner avec un navigateur en utilisant une combinaison des méthodes ci-dessus (j'avais également besoin d'insérer des images de manière dynamique dans le 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');
    }
});

Remarque: Vous devrez fournir un état booléen valide pour la variable isIE.

2
Justin Vincent

Après avoir lu les solutions intéressantes sur cette page, j'ai créé une solution facile à utiliser, fortement influencée par les publications de SLaks et Noyo, qui semble fonctionner sur des versions assez récentes (au moment de l'écriture) de Chrome, IE, Firefox, Safari et. Opera (tout sous Windows). En outre, cela a fonctionné sur un émulateur iPhone/iPad que j'ai utilisé.

Une différence majeure entre cette solution et celle de SLaks et de Noyo est que cette solution vérifie principalement les propriétés naturalWidth et naturalHeight. J'ai constaté que dans les versions actuelles du navigateur, ces deux propriétés semblent fournir les résultats les plus utiles et les plus cohérents.

Ce code renvoie VRAI quand une image a été chargée complètement ET correctement. Il renvoie FALSE lorsqu'une image n'a pas encore été chargée complètement OR échec du chargement.

Vous devez être conscient du fait que cette fonction renvoie également FALSE si l’image est une image 0x0 pixel. Mais ces images sont assez rares, et je ne peux pas penser à un cas très utile dans lequel vous voudriez vérifier si une image 0x0 pixel a déjà été chargée :)

Premièrement, nous attachons une nouvelle fonction appelée "isLoaded" au prototype HTMLImageElement, afin que la fonction puisse être utilisée sur n’importe quel élément d’image.

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;

};

Ensuite, chaque fois que nous devons vérifier l'état de chargement de l'image, nous appelons simplement la fonction "isLoaded".

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

Commentaire de Per giorgian sur le post de SLaks et Noyo, cette solution ne peut probablement être utilisée que comme une vérification ponctuelle de Safari Mobile si vous envisagez de modifier l'attribut SRC. Mais vous pouvez contourner ce problème en créant un élément d'image avec un nouvel attribut SRC au lieu de modifier l'attribut SRC sur un élément d'image existant.

2
data-dan

Si j'ai bien compris, la propriété .complete n'est pas standard. Ce n'est peut-être pas universel ... Je remarque que cela semble fonctionner différemment dans Firefox vers IE. Je charge un certain nombre d'images en javascript, puis vérifie si elles sont complètes. Dans Firefox, cela semble bien fonctionner. Dans IE, ce n'est pas le cas, car les images semblent se charger sur un autre thread. Cela ne fonctionne que si je mets un délai entre mon affectation à image.src et lorsque je vérifie la propriété image.complete.

Utiliser image.onload et image.onerror ne fonctionne pas pour moi non plus, car je dois passer un paramètre pour savoir de quelle image je parle lorsque la fonction est appelée. Toute façon de le faire semble échouer, car elle semble en fait transmettre la même fonction, et non des instances différentes de la même fonction. Donc, la valeur que j'y passe pour identifier l'image finit toujours par être la dernière valeur de la boucle. Je ne vois aucun moyen de contourner ce problème.

Sur Safari et Chrome, je vois les images image.complete true et naturalWidth définies même lorsque la console d'erreur affiche un 404 pour cette image ... et j'ai volontairement supprimé cette image pour la tester. Mais ce qui précède fonctionne bien pour Firefox et IE.

1
user1018645

Cet extrait de code m'a aidé à résoudre les problèmes de mise en cache du navigateur:

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

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

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

Lorsque le cache du navigateur est désactivé, seul ce code ne fonctionne pas:

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

pour que cela fonctionne, vous devez ajouter:

.each(function() {
     if($(this).prop('complete')) $(this).load();
});
1
Frank
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

// ou en tant que plugin

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

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

Celui-ci a bien fonctionné pour moi :)

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

En utilisant ce code JavaScript, vous pouvez vérifier si l’image est correctement chargée ou non.

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

Essayez ceci

0
Ajay Gupta

J'ai eu beaucoup de problèmes avec le chargement complet d'une image et d'EventListener.

Quoi que j'ai essayé, les résultats n'étaient pas fiables.

Mais ensuite j'ai trouvé la solution. Ce n’est techniquement pas agréable, mais je n’ai jamais eu un échec de chargement d’image.

Ce que j'ai fait:

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

Au lieu de charger l'image une fois, je la charge juste une seconde fois directement après la première fois et les deux passent par le gestionnaire d'événements.

Tous mes maux de tête sont partis!


À propos: vous de Stackoverflow, vous m'avez déjà aidé plus de cent fois. Pour cela, un très grand merci!

0
Scoobeedo Cool