たくさんの画像を含むWebページがあります。画像が利用できない場合があるので、壊れた画像がクライアントのブラウザに表示されます。
JQueryを使用して一連の画像を取得し、それを壊れた画像にフィルタリングしてからsrcを置き換える方法を教えてください。
- 私はjQueryを使ったほうが簡単だと思いましたが、純粋なJavaScriptソリューション、つまりPrestaulが提供するものを使うほうがはるかに簡単であることがわかった。
JavaScriptを使用して画像のソースを再割り当てするために画像のonError
イベントを処理します。
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 以降では非推奨です。代わりに、代わりに.on("error")
を使用してください。
$("img").one("error", function () {
$(this).attr("src", "broken.gif");
});
私のような人が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.Preload
これはデモのコード例です。ロードする画像と見つからない画像を指定して、すべて設定しています。
$('#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
これは壊れた画像をすべて置き換える簡単な方法で、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"),
});
}
});
OPがSRCに取って代わることを検討していた間、私はこの質問を打つ多くの人々が壊れたイメージを隠したいだけかもしれないと確信しています、その場合 この単純な解決策 私にとってはうまくいった
<img src="someimage.jpg" onerror="this.style.display='none';" />
私は自分のニーズに合ったスクリプトを見つけることができなかったので、私は壊れた画像をチェックし、それらが修正されるまでそれらを4秒毎にリロードしようと試みる再帰関数を作りました。
それがロードされていないかのように私はそれを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);
});
これは巧妙なテクニックですが、ほとんど保証されています。
<img ... onerror="this.parentNode.removeChild(this);">
これは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] );
}
これにはGitHubの独自のフェッチを使用できます。
フロントエンド: https://github.com/github/fetch
またはバックエンドの場合はNode.jsバージョン: https://github.com/bitinn/node-fetch
fetch(url)
.then(function(res) {
if (res.status == '200') {
return image;
} else {
return placeholder;
}
}
編集:このメソッドはXHRを置き換えようとしており、おそらくすでにChromeに入っています。将来これを読む人には、前述のライブラリを含める必要はないかもしれません。
:$("div").innerHTML = <img src="wrong-uri">
のようにimg
をinnerHTML
で挿入した場合、失敗した場合は別の画像を読み込むことができます。例えば:
<script>
function imgError(img) {
img.error="";
img.src="valid-uri";
}
</script>
<img src="wrong-uri" onerror="javascript:imgError(this)">
なぜjavascript: _
が必要なのですか? innerHTML
のscriptタグを介してDOMに注入されたスクリプトは、注入された時点では実行されないため、明示的に指定する必要があります。
これはJQueryによってラップされたHTML5 Imageオブジェクトを使った例です。プライマリイメージ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>
"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\(['"](.+)['"]\)/, '$1');
$('<img>', {
src: currentUrl
}).on("error", function(e) {
$this = $(this);
$this.css({
"background-image": defaultUrl
})
e.target.remove()
}.bind(this))
})
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;
}
より良い通話
jQuery(window).load(function(){
$.imgReload();
});
document.ready
を使用する必要がないのは、画像のみがロードされることを意味するのではなく、HTMLのみがロードされるためです。したがって、遅延通話は必要ありません。
CoffeeScript の亜種:
Turbolinksに関する問題を解決するために、画像が実際に表示されていてもFirefoxで.error()メソッドが呼び出されることがある問題を修正しました。
$("img").error ->
e = $(@).get 0
$(@).hide() if !$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0)
純粋なJS私の仕事は次のとおりです。image 'bl-once.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();
}
}
}
}
};
だから、それは私のsrcまたは現在のディレクトリからの 'no-image.png'に正しい 'needed.png'を挿入するでしょう。
this other SO post を見ながらこの投稿を見つけました。以下は私がそこに出した答えのコピーです。
私はこれが古いスレッドであることを知っています、しかしReactは普及してきていて、そしておそらく、Reactを使っている誰かが同じ問題に対する答えを探してここに来るでしょう。
したがって、Reactを使用している場合は、以下のようにすることができます。これは、ReactチームのBen Alpertが提供したオリジナルの回答です here
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} />;
);
}
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" );
私はこれら二つの簡単な機能で私の問題を解決した:
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');
}
});
}
もっと良い方法があるかどうかはわかりませんが、それを実現するためのハックを考えることができます。Ajaxでimg URLに投稿し、応答を解析して画像が実際に戻ってきたかどうかを確認できます。それが404か何かとして戻ってきた場合は、次にimgを交換してください。私はこれがかなり遅いと予想しますが。
これは何年もの間私をいらいらさせています。私のCSS修正はimg
に背景画像を設定します。動的画像src
がフォアグラウンドにロードされない場合、プレースホルダーはimg
のbgに表示されます。あなたの画像がデフォルトサイズ(例えばheight
、min-height
、width
、そして/またはmin-width
)を持っているなら、これは働きます。
あなたは壊れた画像アイコンを見るでしょうが、それは改善です。 IE9まで正常にテストされました。 iOS SafariとChromeは壊れたアイコンさえ表示しません。
.dynamicContainer img {
background: url('/images/placeholder.png');
background-size: contain;
}
小さなアニメーションを追加して、背景のちらつきなしにsrc
をロードする時間を与えます。 Chromeはバックグラウンドでスムーズにフェードインしますが、デスクトップの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; }
}
バックアップイメージがロードされない場合でも、window
の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
に入れて、最初のインラインスクリプトとして実行します。それで、それはスクリプトの後に起こるエラーを聞きます。
特にバブリングしないイベントの場合は、イベントキャプチャを使用してエラーをキャッチします。
各画像でイベントをバインドしないようにするイベント委任を使用します。
以下のようにbackup.png
の消滅とそれに続く無限ループを回避するためにbackup.png
を与えた後、error img
要素に属性を与えてください:
img error-> backup.png-> error-> backup.png-> error - > ,
画像をロードできない場合(たとえば、指定されたURLに存在しないため)、画像のURLはデフォルトに変更されます。
。error() について
$('img').on('error', function (e) {
$(this).attr('src', 'broken.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] || ''; });
});
};
あなたは$*
を通して失敗したimageオブジェクトからプレースホルダーパスを渡して、その中ですべてのプロパティにアクセスすることができます:
$('img').fallback('http://dummyimage.com/$widthx$height&text=$src');
私は同じ問題を抱えています。このコードは私の場合はうまくいきます。
// 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;
}
}
最初にロードできなかったイメージがDOMから完全に削除された場合、これが最もうまくいくことがわかりました。 404エラーはtry/catchブロックで省略できないため、console.clear()
を実行するとコンソールウィンドウがきれいに保たれます。
$('img').one('error', function(err) {
// console.log(JSON.stringify(err, null, 4))
$(this).remove()
console.clear()
})