web-dev-qa-db-fra.com

Manière indépendante du navigateur de détecter quand l'image a été chargée

Dans IE, vous pouvez exécuter un changement de compte. Il y a de la charge, mais j'ai lu des choses effrayantes . jQuery résume assez bien l'événement load du DOM avec "ready". Il semble probable que j'ignore tout simplement le chargement d'images par une autre bibliothèque de Nice. 

Le contexte est que je génère des images de manière dynamique (via des rappels de serveur) pouvant prendre un certain temps de téléchargement. Dans mon code réservé à IE, je définis le src de l'élément img, puis lorsque l'événement onreadystatechange se déclenche avec le statut "complete", je l'ajoute au DOM afin que l'utilisateur le voie.

Je serais heureux avec une solution JavaScript "native", ou un pointeur sur une bibliothèque qui fait le travail. Il y a tellement de bibliothèques et je suis sûr que c'est un cas où je ne connais tout simplement pas la bonne. Cela dit, nous sommes déjà des utilisateurs de jQuery, je ne suis donc pas pressé d’ajouter une très grande bibliothèque pour obtenir cette fonctionnalité.

55
Sebastian Good

NOTE: J'ai écrit ceci en 2010, les navigateurs à l'état sauvage étaient IE 8/9 beta, Firefox 3.x et Chrome 4.x. Veuillez utiliser ceci à des fins de recherche uniquement. Je doute que vous puissiez copier/coller ceci dans un navigateur moderne et le faire fonctionner sans problème.

AVERTISSEMENT: Nous sommes en 2017 maintenant, je reçois toujours des points à ce sujet. Utilisez-le uniquement à des fins de recherche. Je n'ai actuellement aucune idée de la façon de détecter l'état de chargement des images, mais il existe probablement des moyens beaucoup plus élégants de le faire ... au moins j'espère sincèrement qu'il y en a. Je recommande fortement de ne pas utiliser mon code dans un environnement de production sans plus de recherche.


Je suis un peu en retard pour cette fête, peut-être que cette réponse aidera quelqu'un d'autre ...

Si vous utilisez jQuery, ne vous embêtez pas avec les gestionnaires d'événements stock (onclick/onmouseover/etc), arrêtez simplement de les utiliser. Utilisez les méthodes d'événement qu'ils ont fournies dans leur API .


Cela alertera, avant que l'image soit ajoutée au corps, car l'événement de chargement est déclenché lorsque l'image est chargée en mémoire. Il fait exactement ce que vous lui dites: créez une image avec le src de test.jpg, lorsque test.jpg charge une alerte, puis ajoutez-la au corps.

var img = $('<img src="test.jpg" />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);

Cela alertera, une fois que l'image est insérée dans le corps, encore une fois, en faisant ce que vous lui avez dit: créer une image, définir un événement no src), définissez maintenant le src ... maintenant l'image est chargée et l'événement est déclenché.

var img = $('<img />');
img.load(function() {
    alert('Image Loaded');
});
$('body').append(img);
$img.attr('src','test.jpg');

Vous pouvez bien sûr aussi ajouter un gestionnaire d'erreurs et fusionner un tas d'événements en utilisant bind ().

var img = $('<img />');
img.bind({
    load: function() {
        alert('Image loaded.');
    },
    error: function() {
        alert('Error thrown, image didn\'t load, probably a 404.');
    }
});
$('body').append(img);
img.attr('src','test.jpg');

À la demande de @ChrisKempen ...

Voici un moyen non déterminé par les événements de déterminer si les images sont brisées après le chargement du DOM. Ce code est un dérivé du code d'un article de StereoChrome qui utilise les attributs naturalWidth, naturalHeight et complete pour déterminer si l'image existe.

$('img').each(function() {
    if (this.naturalWidth === 0 || this.naturalHeight === 0 || this.complete === false) {
        alert('broken image');
    }
});
47
Paul J

Selon la spécification du W3C , uniquement les éléments BODY et FRAMESET fournissent un événement "onload" à associer. Certains navigateurs le supportent indépendamment, mais sachez qu'il n'est pas nécessaire d'implémenter les spécifications W3C.

Quelque chose qui pourrait être pertinent pour cette discussion, mais pas nécessairement la réponse dont vous avez besoin, est cette discussion:

L'événement Image.onload ne se déclenche pas sur Internet Explorer lorsque l'image est en cache


Autre chose qui peut être lié _ à vos besoins, bien que ce ne soit pas le cas, cette information concerne-t-elle la prise en charge d'un événement «onload» synthétisé pour tout élément chargé dynamiquement élément DOM:

Comment puis-je déterminer si un élément DOM créé de manière dynamique a été ajouté au DOM?

10
Jason Bunting

Le seul moyen fiable que j'ai trouvé est de tout faire du côté client, comme ceci.

var img = new Image();
img.onload = function() {
  alert('Done!');
}
img.src = '/images/myImage.jpg';
5
Josh Stodola

Je pense que onload devrait bien fonctionner. Devez-vous générer le balisage pour les images ou pouvez-vous les ajouter de manière statique? Si ce dernier, je suggérerais ce qui suit:

<img src="foo.png" class="classNeededToHideImage" onload="makeVisible(this)">

Vous pouvez également utiliser window.onload pour rendre toutes les images visibles en une fois. window.onload se déclenche une fois que toutes les ressources externes ont été chargées.

Si vous souhaitez ajouter les images de manière dynamique, vous devez d'abord attendre que le DOM soit prêt à être modifié, c'est-à-dire utiliser jQuery ou implémenter votre propre hack DOMContentLoaded pour les navigateurs qui ne le prennent pas en charge de manière native.

Ensuite, vous créez vos objets image, affectez des auditeurs onload pour les rendre visibles et/ou ajoutez-les au document.

Encore mieux (mais légèrement plus compliqué) serait de créer et de commencer à charger les images immédiatement lorsque le script s’exécutera. Sur DOMContentLoaded, vous devez vérifier chaque image pour complete afin de décider de les ajouter immédiatement au document ou d'attendre que l'écouteur onload de l'image se déclenche.

3
Christoph

Bon, je vais essayer de résumer les différentes réponses partielles ici (y compris la mienne).

Il semblerait que la solution consiste à utiliser la charge, qui est "largement prise en charge" bien que non officiellement requise par les normes. Notez que pour IE en particulier, vous devez définir onLoad avant de définir l'attribut src, sinon il risque de ne pas se déclencher lors du chargement d'une image à partir du cache. Dans tous les cas, cela semble être la meilleure pratique: configurez vos gestionnaires d’événements avant de commencer à déclencher des événements. Lorsque la charge n'est pas prise en charge, il faut supposer que la fonctionnalité n'est tout simplement pas disponible.

3
Sebastian Good

Si je ne me trompe pas en javascript, une balise image contient les événements onload et onerror

voici un morceau de code intéressant que j'ai fait pour cacher les images brisées

dans une balise de style

img.failed{
   display:none;
}

en utilisant img onerror, j’avais un morceau de javascript qui faisait this.className = failed et il cacherait l’image en cas d’erreur

cependant, j'ai peut-être mal compris votre objectif

1
Jim

Il semblerait que la réponse est d'utiliser onreadystatechange dans IE et onLoad dans d'autres navigateurs. Si aucun des deux n'est disponible, faites autre chose. onLoad serait préférable, mais IE ne le déclenche pas lors du chargement d'une image à partir du cache, comme indiqué dans l'une des réponses ci-dessous. 

1
Sebastian Good

HTML

<img id="myimage" src="http://farm4.static.flickr.com/3106/2819995451_23db3f25fe_t.jpg"/>​

SCRIPT

setTimeout(function(){
    $('#myimage').attr('src','http://cdn.redmondpie.com/wp-content/uploads/2011/05/canarylogo.png').load(function(){
        alert('Main Image Loaded');

        $('#myimage').attr('src','image.jpg').bind({
            load: function(){
                alert('Image loaded.');
            },
            error: function(){
                alert('Image not loaded.');
            }
        });
    });
},1000);

JS Fiddle

http://jsfiddle.net/gerst20051/sLge3/

1
Andy

Utiliser un URI de données est la voie à suivre. Cependant, l'utilisation d'un fichier SVG au lieu d'un fichier GIF offre plus de flexibilité. Vous pouvez changer rapidement la taille. Il suffit de lancer ceci dans une console JavaScript:

var width = 1;
var height = 1;
'data:image/svg+xml;base64,' +
btoa(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"/>`);

Exemple de sortie:

data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxIiBoZWlnaHQ9IjEiLz4=

J'ai jeté ensemble un utilitaire rapide CodePen pour créer des SVG transparents avec des dimensions arbitraires . C'est assez basique, vous devrez donc le modifier si vous souhaitez ajouter de la couleur ou d'autres fonctionnalités à l'image.

L'avantage principal par rapport à une image à un pixel est qu'elle permet de conserver les proportions. Ceci est important pour les images de taille dynamique, car la mise en page est souvent effectuée avant que la variable src ne devienne une image réelle (si c'est le but recherché). Jusqu'à ce que la src change, l'image sera carrée, ce qui peut être indésirable.

0
Zenexer