Обнаружение сбоя загрузки изображения в Javascript

есть ли способ определить, приводит ли путь изображения к фактическому изображению, т. е. определить, когда изображение не загружается в Javascript.

для веб-приложения я анализирую xml-файл и динамически создаю HTML-изображения из списка путей к изображениям. Некоторые пути изображений могут больше не существовать на сервере, поэтому я хочу изящно ошибиться, обнаружив, какие изображения не загружаются и удаляя этот элемент HTML img.

Примечание решения JQuery не смогут использоваться(босс не хочет чтобы использовать JQuery, да, я знаю, что не начинаю). Я знаю, как в JQuery определить, когда загружается изображение, но не удалось ли это.

мой код для создания элементов img, но как я могу определить, приводит ли путь img к неудачной загрузке изображения?

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

7 ответов


вы можете попробовать следующий код. Я не могу ручаться за совместимость браузера, поэтому вам придется проверить это.

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

и мои симпатии к jQuery-упорному боссу!


ответ хороший, но он вводит одну проблему. Всякий раз, когда вы назначаете onload или onerror непосредственно, он может заменить обратный вызов, который был назначен ранее. Вот почему есть хороший метод, который "регистрирует указанный прослушиватель на EventTarget он вызывается на" как говорится в MDN. Вы можете зарегистрировать столько слушателей, сколько вы хотите на том же событии.

позвольте мне немного переписать ответ.

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

потому что внешний процесс загрузки ресурсов асинхронный, было бы еще приятнее использовать современный JavaScript с обещаниями, такими как следующее.

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

);

Это:

<img onerror="this.src='/images/image.png'" src="...">

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

вот функция, которую я написал для другого ответа: Javascript Url Изображения Проверить. Я не знаю, если это именно то, что вам нужно, но он использует различные методы, которые можно использовать, которые включают обработчики onload, onerror, onabort и общий тайм-аут.

поскольку загрузка изображений асинхронна, вы вызываете эту функцию с вашим изображением, а затем она вызывает ваш обратный вызов через некоторое время с результатом.


jQuery + CSS для img

С jQuery это работает для меня:

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

и я могу использовать эту картинку везде на моем сайте независимо от ее размера со следующим свойством CSS3:

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

Совет 1: Используйте изображение не менее 800 x 800 пикселей.

Совет 2: для использования с портрет людей используйте object-position: 20% 50%;

CSS только для фон-ИМГ

для отсутствующих фоновых изображений я также добавил следующее На каждом background-image объявления :

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

примечание : не работает для прозрачных изображений.

серверная сторона Apache

другое решение-обнаружить отсутствующее изображение с Apache, прежде чем отправлять его в браузер и размещать его по умолчанию no-img.содержание ПНГ.

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

просто, как показано ниже:

var img = new Image(); 
img.src = imgUrl; 

if (!img.complete) {

//has picture
}
else //not{ 

}