web-dev-qa-db-fra.com

Détecter le chargement d'une image en Javascript

Existe-t-il un moyen de déterminer si un chemin d’image conduit à une image réelle, c’est-à-dire si un fichier ne parvient pas à se charger en Javascript?.

Pour une application Web, j'analyse un fichier XML et crée dynamiquement des images HTML à partir d'une liste de chemins d'accès aux images. Il se peut que certains chemins d’image n’existent plus sur le serveur. Par conséquent, je souhaite échouer en détectant les images qui ne se chargent pas et en supprimant cet élément HTML img.

Remarque Les solutions JQuery ne pourront pas être utilisées (le chef ne veut pas utiliser JQuery, oui, je ne le fais pas.) Je connais un moyen dans JQuery de détecter le moment où une image est chargée, mais pas si elle a échoué.

Mon code pour créer des éléments img, mais comment puis-je détecter si le chemin d'accès à img entraîne l'échec du chargement de l'image?

var imgObj = new Image();  // document.createElement("img");
imgObj.src = src;
83
sazr

Vous pouvez essayer le code suivant. Je ne peux cependant pas garantir la compatibilité du navigateur, vous devrez donc le tester.

function testImage(URL) {
    var tester=new Image();
    tester.onload=imageFound;
    tester.onerror=imageNotFound;
    tester.src=URL;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");

Et mes sympathies pour le patron jQuery-résistant!

93
Nikhil

La réponse est bonne, mais cela pose un problème. Chaque fois que vous affectez directement onload ou onerror, il peut remplacer le rappel affecté précédemment. C’est pourquoi il existe une méthode de Nice qui "enregistre l’auditeur spécifié sur le EventTarget sur lequel il est appelé" comme on le dit sur MDN . Vous pouvez inscrire autant d'auditeurs que vous le souhaitez sur le même événement.

Permettez-moi de récrire un peu la réponse.

function testImage(url) {
    var tester = new Image();
    tester.addEventListener('load', imageFound);
    tester.addEventListener('error', imageNotFound);
    tester.src = url;
}

function imageFound() {
    alert('That image is found and loaded');
}

function imageNotFound() {
    alert('That image was not found.');
}

testImage("http://foo.com/bar.jpg");

Le processus de chargement des ressources externes étant asynchrone, il serait encore plus judicieux d'utiliser du JavaScript moderne avec des promesses, telles que les suivantes.

function testImage(url) {

    // Define the promise
    const imgPromise = new Promise(function imgPromise(resolve, reject) {

        // Create the image
        const imgElement = new Image();

        // When image is loaded, resolve the promise
        imgElement.addEventListener('load', function imgOnLoad() {
            resolve(this);
        });

        // When there's an error during load, reject the promise
        imgElement.addEventListener('error', function imgOnError() {
            reject();
        })

        // Assign URL
        imgElement.src = url;

    });

    return imgPromise;
}

testImage("http://foo.com/bar.jpg").then(

    function fulfilled(img) {
        console.log('That image is found and loaded', img);
    },

    function rejected() {
        console.log('That image was not found');
    }

);
35
emil.c

Cette:

<img onerror="this.src='/images/image.png'" src="...">
17
Rafael Martins
/**
 * Tests image load.
 * @param {String} url
 * @returns {Promise}
 */
function testImageUrl(url) {
  return new Promise(function(resolve, reject) {
    var image = new Image();
    image.addEventListener('load', resolve);
    image.addEventListener('error', reject);
    image.src = url;
  });
}

return testImageUrl(imageUrl).then(function imageLoaded(e) {
  return imageUrl;
})
.catch(function imageFailed(e) {
  return defaultImageUrl;
});
4
holmberd

jQuery + CSS pour img

Avec jQuery cela fonctionne pour moi:

$('img').error(function() {
    $(this).attr('src', '/no-img.png').addClass('no-img');
});

Et je peux utiliser cette image partout sur mon site Web, quelle que soit sa taille, avec la propriété CSS3 suivante:

img.no-img {
    object-fit: cover;
    object-position: 50% 50%;
}

CONSEIL 1: utilisez une image carrée d'au moins 800 x 800 pixels.

CONSEIL 2: à utiliser avec portrait de personnes, utilisez object-position: 20% 50%;

CSS uniquement pour background-img

Pour les images d’arrière-plan manquantes, j’ai également ajouté ce qui suit sur chaque background-image déclaration:

background-image: url('path-to-image.png'), url('no-img.png');

REMARQUE: ne fonctionne pas pour les images transparentes.

Apache côté serveur

Une autre solution consiste à détecter les images manquantes avec Apache avant de les envoyer au navigateur et de les remplacer par le contenu par défaut de no-img.png.

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} /images/.*\.(gif|jpg|jpeg|png)$
RewriteRule .* /images/no-img.png [L,R=307]
3
Meloman

Voici une fonction que j'ai écrite pour une autre réponse: Javascript Image Url Verify . Je ne sais pas si c'est exactement ce dont vous avez besoin, mais il utilise différentes techniques que vous utiliseriez, notamment des gestionnaires pour onload, onerror, onabort et un délai général .

Le chargement de l'image étant asynchrone, vous appelez cette fonction avec votre image, puis votre rappel est renvoyé un peu plus tard avec le résultat.

3
jfriend00