jQuery / JavaScript для замены сломанных изображений
У меня есть веб-страницу, которая включает в себя кучу образов. Иногда изображение недоступно, поэтому в браузере клиента отображается сломанное изображение.
Как использовать jQuery для получения набора изображений, фильтровать его на сломанные изображения, а затем заменить src?
--Я думал, что будет проще сделать это с помощью jQuery, но оказалось намного проще просто использовать чистое решение JavaScript, то есть то, которое предоставлено Prestaul.
30 ответов
обработки onError
событие для изображения, чтобы переназначить его источник с помощью JavaScript:
function imgError(image) {
image.onerror = "";
image.src = "/images/noimage.gif";
return true;
}
<img src="image.png" onerror="imgError(this);"/>
или без функции JavaScript:
<img src="image.png" onError="this.onerror=null;this.src='/images/noimage.gif';" />
в следующей таблице совместимости перечислены браузеры, которые поддерживают средство ошибки:
программа error
обработчик:
$("img").error(function () {
$(this).unbind("error").attr("src", "broken.gif");
});
error()
осуждается в 1.8 или выше.
в случае, если кто-то, как я, пытается прикрепить error
событие для динамического HTML img
тег, я хотел бы отметить, что есть одна загвоздка:
видимо img
событий ошибки не пузырь в большинстве браузеров, вопреки тому, что стандартный говорит.
так, что-то вроде следующего будет не работает:
$(document).on('error', 'img', function () { ... })
надеюсь это будет полезно кому-то еще. Жаль, что я не видел этого здесь, в эта тема. Но я этого не сделал. Итак, я добавляю его
вот вам самостоятельное решение:
$(window).load(function() {
$('img').each(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
// image was broken, replace with your new image
this.src = 'http://www.tranism.com/weblog/images/broken_ipod.gif';
}
});
});
Я считаю, что это то, что вы после: С помощью jQuery.Поджатие
вот пример кода из демо, вы указываете загрузку и не нашли изображения, и все готово:
$('#images img').preload({
placeholder:'placeholder.jpg',
notFound:'notfound.jpg'
});
$(window).bind('load', function() {
$('img').each(function() {
if((typeof this.naturalWidth != "undefined" &&
this.naturalWidth == 0 )
|| this.readyState == 'uninitialized' ) {
$(this).attr('src', 'missing.jpg');
}
}); })
источник:http://www.developria.com/2009/03/jquery-quickie---broken-images.html
это дерьмовый метод, но это в значительной степени гарантировано:
<img ... onerror="this.parentNode.removeChild(this);">
в то время как OP искал замену SRC, я уверен, что многие люди, задающие этот вопрос, могут только хотеть скрыть сломанное изображение, и в этом случае Это простое решение отлично сработало для меня:
<img src="someimage.jpg" onerror="this.style.display='none';" />
вот быстрый и грязный способ, чтобы заменить все сломанные изображения, и нет необходимости менять HTML код ;)
$("img").each(function(){
var img = $(this);
var image = new Image();
image.src = $(img).attr("src");
var no_image = "https://dummyimage.com/100x100/7080b5/000000&text=No+image";
if (image.naturalWidth == 0 || image.readyState == 'uninitialized'){
$(img).unbind("error").attr("src", no_image).css({
height: $(img).css("height"),
width: $(img).css("width"),
});
}
});
Я не смог найти сценарий, соответствующий моим потребностям, поэтому я сделал рекурсивную функцию, чтобы проверить сломанные изображения и попытаться перезагрузить их каждые четыре секунды, пока они не будут исправлены.
Я ограничил его 10 попытками, как будто он не загружен, тогда изображение может не присутствовать на сервере, и функция войдет в бесконечный цикл. Я все еще проверяю. Не стесняйтесь, чтобы настроить его :)
var retries = 0;
$.imgReload = function() {
var loaded = 1;
$("img").each(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
var src = $(this).attr("src");
var date = new Date();
$(this).attr("src", src + "?v=" + date.getTime()); //slightly change url to prevent loading from cache
loaded =0;
}
});
retries +=1;
if (retries < 10) { // If after 10 retries error images are not fixed maybe because they
// are not present on server, the recursion will break the loop
if (loaded == 0) {
setTimeout('$.imgReload()',4000); // I think 4 seconds is enough to load a small image (<50k) from a slow server
}
// All images have been loaded
else {
// alert("images loaded");
}
}
// If error images cannot be loaded after 10 retries
else {
// alert("recursion exceeded");
}
}
jQuery(document).ready(function() {
setTimeout('$.imgReload()',5000);
});
вы можете использовать собственную выборку GitHub для этого:
интерфейс:https://github.com/github/fetch
или для бэкэнда, узла.версия js:https://github.com/bitinn/node-fetch
fetch(url)
.then(function(res) {
if (res.status == '200') {
return image;
} else {
return placeholder;
}
}
Edit: этот метод собирается заменить XHR и, предположительно, уже был в Chrome. Для тех, кто читает это в будущем, вам может не понадобиться вышеупомянутая библиотека.
это JavaScript, должен быть совместим с кросс-браузером и поставляется без уродливой разметки onerror=""
:
var sPathToDefaultImg = 'http://cdn.sstatic.net/stackexchange/img/logos/so/so-icon.png',
validateImage = function( domImg ) {
oImg = new Image();
oImg.onerror = function() {
domImg.src = sPathToDefaultImg;
};
oImg.src = domImg.src;
},
aImg = document.getElementsByTagName( 'IMG' ),
i = aImg.length;
while ( i-- ) {
validateImage( aImg[i] );
}
лучше позвонить с помощью
jQuery(window).load(function(){
$.imgReload();
});
потому что с помощью document.ready
Не обязательно означает, что изображения загружаются, только HTML. Таким образом, нет необходимости в отложенном звонке.
CoffeeScript вариант:
Я сделал это, чтобы исправить проблему с Turbolinks, которая вызывает .метод error (), чтобы подняться в Firefox иногда, даже если изображение действительно есть.
$("img").error ->
e = $(@).get 0
$(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
С помощью Prestaul это, я добавил некоторые проверки, и я предпочитаю использовать способ jQuery.
<img src="image1.png" onerror="imgError(this,1);"/>
<img src="image2.png" onerror="imgError(this,2);"/>
function imgError(image, type) {
if (typeof jQuery !== 'undefined') {
var imgWidth=$(image).attr("width");
var imgHeight=$(image).attr("height");
// Type 1 puts a placeholder image
// Type 2 hides img tag
if (type == 1) {
if (typeof imgWidth !== 'undefined' && typeof imgHeight !== 'undefined') {
$(image).attr("src", "http://lorempixel.com/" + imgWidth + "/" + imgHeight + "/");
} else {
$(image).attr("src", "http://lorempixel.com/200/200/");
}
} else if (type == 2) {
$(image).hide();
}
}
return true;
}
если вы вставили свой img
С innerHTML
, например: $("div").innerHTML = <img src="wrong-uri">
, вы можете загрузить другое изображение, если это не удается сделать, e.g, это:
<script>
function imgError(img) {
img.error="";
img.src="valid-uri";
}
</script>
<img src="wrong-uri" onerror="javascript:imgError(this)">
почему javascript: _
нужен? Потому что скрипты, введенные в DOM через теги скриптов в innerHTML
не запускаются в то время, когда они вводятся, поэтому вы должны быть явными.
Я нашел этот пост, глядя на этот другой так пост. Ниже приводится копия ответа, который я там дал.
Я знаю, что это старый поток, но React стал популярным, и, возможно, кто-то, использующий React, придет сюда в поисках ответа на ту же проблему.
Итак, если вы используете React, вы можете сделать что-то вроде приведенного ниже, что было оригинальным ответом, предоставленным Беном Альпертом из команды React здесь
getInitialState: function(event) {
return {image: "http://example.com/primary_image.jpg"};
},
handleError: function(event) {
this.setState({image: "http://example.com/failover_image.jpg"});
},
render: function() {
return (
<img onError={this.handleError} src={src} />;
);
}
Я создал скрипка для замены сломанного изображения с помощью события" onerror". Это может вам помочь.
//the placeholder image url
var defaultUrl = "url('https://sadasd/image02.png')";
$('div').each(function(index, item) {
var currentUrl = $(item).css("background-image").replace(/^url\(['"](.+)['"]\)/, '');
$('<img>', {
src: currentUrl
}).on("error", function(e) {
$this = $(this);
$this.css({
"background-image": defaultUrl
})
e.target.remove()
}.bind(this))
})
вот пример использования объекта изображения HTML5, обернутого JQuery. Вызовите функцию load для основного URL-адреса образа, и если эта загрузка вызывает ошибку, замените атрибут src образа URL-адресом резервной копии.
function loadImageUseBackupUrlOnError(imgId, primaryUrl, backupUrl) {
var $img = $('#' + imgId);
$(new Image()).load().error(function() {
$img.attr('src', backupUrl);
}).attr('src', primaryUrl)
}
<img id="myImage" src="primary-image-url"/>
<script>
loadImageUseBackupUrlOnError('myImage','primary-image-url','backup-image-url');
</script>
чистый JS. Моя задача была: если изображение ' BL-один раз.png " пуст - > вставить первое (не имеющее статуса 404) изображение из списка массивов (в текущем каталоге):
<img src="http://localhost:63342/GetImage/bl-once.png" width="200" onerror="replaceEmptyImage.insertImg(this)">
возможно, его нужно улучшить, но:
var srcToInsertArr = ['empty1.png', 'empty2.png', 'needed.png', 'notActual.png']; // try to insert one by one img from this array
var path;
var imgNotFounded = true; // to mark when success
var replaceEmptyImage = {
insertImg: function (elem) {
if (srcToInsertArr.length == 0) { // if there are no more src to try return
return "no-image.png";
}
if(!/undefined/.test(elem.src)) { // remember path
path = elem.src.split("/").slice(0, -1).join("/"); // "http://localhost:63342/GetImage"
}
var url = path + "/" + srcToInsertArr[0];
srcToInsertArr.splice(0, 1); // tried 1 src
if(imgNotFounded){ // while not success
replaceEmptyImage.getImg(url, path, elem); // CALL GET IMAGE
}
},
getImg: function (src, path, elem) { // GET IMAGE
if (src && path && elem) { // src = "http://localhost:63342/GetImage/needed.png"
var pathArr = src.split("/"); // ["http:", "", "localhost:63342", "GetImage", "needed.png"]
var name = pathArr[pathArr.length - 1]; // "needed.png"
xhr = new XMLHttpRequest();
xhr.open('GET', src, true);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.status == 200) {
elem.src = src; // insert correct src
imgNotFounded = false; // mark success
}
else {
console.log(name + " doesn't exist!");
elem.onerror();
}
}
}
}
};
Так, это вставить правильно необходимо.png "для моего src или" no-image.ПНГ с текущего каталога.
Я не уверен, что есть лучший способ, но я могу придумать хак, чтобы получить его - вы могли бы AJAX опубликовать URL-адрес img и проанализировать ответ, чтобы увидеть, действительно ли изображение вернулось. Если он вернулся как 404 или что-то еще, то замените img. Хотя я ожидаю, что это будет довольно медленно.
Я решил свою проблему с помощью этих двух простых функций:
function imgExists(imgPath) {
var http = jQuery.ajax({
type:"HEAD",
url: imgPath,
async: false
});
return http.status != 404;
}
function handleImageError() {
var imgPath;
$('img').each(function() {
imgPath = $(this).attr('src');
if (!imgExists(imgPath)) {
$(this).attr('src', 'images/noimage.jpg');
}
});
}
jQuery 1.8
// If missing.png is missing, it is replaced by replacement.png
$( "img" )
.error(function() {
$( this ).attr( "src", "replacement.png" );
})
.attr( "src", "missing.png" );
jQuery 3
// If missing.png is missing, it is replaced by replacement.png
$( "img" )
.on("error", function() {
$( this ).attr( "src", "replacement.png" );
})
.attr( "src", "missing.png" );
;(window.jQuery || window.Zepto).fn.fallback = function (fallback) {
return this.one('error', function () {
var self = this;
this.src = (fallback || 'http://lorempixel.com/$width/$height')
.replace(/$(\w+)/g, function (m, t) { return self[t] || ''; });
});
};
вы можете передать путь заполнителя и получить доступ ко всем свойствам из неудачного объекта изображения через $*
:
$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');
это расстраивало меня в течение многих лет. Мое исправление CSS устанавливает фоновое изображение на img
. Когда динамическое изображение src
не загружается на передний план, заполнитель виден на img
' s bg. Это работает, если ваши изображения имеют размер по умолчанию (например,height
, min-height
, width
и/или min-width
).
вы увидите значок сломанного изображения, но это улучшение. Протестировано до IE9 успешно. iOS Safari и Chrome даже не показывают сломанный икона.
.dynamicContainer img {
background: url('/images/placeholder.png');
background-size: contain;
}
добавить немного анимации, чтобы дать src
время загрузки без фонового мерцания. Chrome плавно исчезает в фоновом режиме, но desktop Safari этого не делает.
.dynamicContainer img {
background: url('/images/placeholder.png');
background-size: contain;
-webkit-animation: fadein 1s;
animation: fadein 1s;
}
@-webkit-keyframes fadein {
0% { opacity: 0.0; }
50% { opacity: 0.5; }
100% { opacity: 1.0; }
}
@keyframes fadein {
0% { opacity: 0.0; }
50% { opacity: 0.5; }
100% { opacity: 1.0; }
}
Если изображение не может быть загружено (например, потому что его нет в предоставленном URL-адресе), URL-адрес изображения будет изменен на default,
подробнее о .error ()
$('img').on('error', function (e) {
$(this).attr('src', 'broken.png');
});
Я думаю, что у меня есть более элегантный способ с делегированием событий и захватом событий на window
' s error
даже если не удается загрузить резервный образ.
img {
width: 100px;
height: 100px;
}
<script>
window.addEventListener('error', windowErrorCb, {
capture: true
}, true)
function windowErrorCb(event) {
let target = event.target
let isImg = target.tagName.toLowerCase() === 'img'
if (isImg) {
imgErrorCb()
return
}
function imgErrorCb() {
let isImgErrorHandled = target.hasAttribute('data-src-error')
if (!isImgErrorHandled) {
target.setAttribute('data-src-error', 'handled')
target.src = 'backup.png'
} else {
//anything you want to do
console.log(target.alt, 'both origin and backup image fail to load!');
}
}
}
</script>
<img id="img" src="error1.png" alt="error1">
<img id="img" src="error2.png" alt="error2">
<img id="img" src="https://i.stack.imgur.com/ZXCE2.jpg" alt="avatar">
суть :
вставить код в тег
head
и выполняется как первый встроенный скрипт. Таким образом, он будет слушать ошибки, возникающие после сценария.используйте захват событий, чтобы поймать ошибки, особенно для тех событий, которые не кипятись.
используйте делегирование событий, которое позволяет избежать привязки событий к каждому изображению.
дает ошибку
img
элемент атрибут после предоставления имbackup.png
чтобы избежать исчезновенияbackup.png
и последующий бесконечный цикл, как показано ниже:
ошибка img - >резервное копирование.png - >ошибка - >резервное копирование.ПНГ->ошибка->,,,,,
У меня такая же проблема. Этот код хорошо работает в моем случае.
// Replace broken images by a default img
$('img').each(function(){
if($(this).attr('src') === ''){
this.src = '/default_feature_image.png';
}
});
иногда с помощью error
событие невозможно, например, потому, что вы пытаетесь сделать что-то на странице, которая уже загружена, например, когда вы запускаете код через консоль, букмарклет или скрипт, загруженный асинхронно. В таком случае, проверьте, что img.naturalWidth
и img.naturalHeight
0, кажется, делает трюк.
например, вот фрагмент для перезагрузки всех сломанных изображений с консоли:
$$("img").forEach(img => {
if (!img.naturalWidth && !img.naturalHeight) {
img.src = img.src;
}
}
Я использую код ниже, который сначала пытается найти аватар текущего пользователя на основе их идентификатора пользователя, который в этом случае является "123", и если он не находит изображение Аватара, код onerror изменяет img src на изображение-заполнитель.
<img src="avatars/users/123.png" onerror="this.src='/ngTribeBase/src/assets/img/avatars/male.png'" />