jQueryで画像が読み込まれているかどうか(エラーがないかどうか)を確認


224

JavaScriptとjQueryライブラリを使用して、順序付けられていないリストに含まれている画像のサムネイルを操作しています。画像が読み込まれると1つの処理が実行され、エラーが発生すると別の処理が実行されます。イベントとしてjQuery load()error()メソッドを使用しています。これらのイベントの後、私は.completeの画像DOM要素をチェックして、jQueryがイベントを登録する前に画像がまだロードされていないことを確認します。

jQueryがイベントを登録する前にエラーが発生した場合を除いて、正しく動作します。私が考えることができる唯一の解決策は、img onerror属性を使用してグローバルに(またはそれ自体のノードで)どこかに「フラグ」を格納して、jQueryが.completeをチェックするときにその「ストア/ノード」をチェックできるようにすることです。

誰かがより良い解決策を持っていますか?

編集:太字の主なポイントと以下の追加の詳細を追加しました: 画像にロードイベントとエラーイベントを追加した後、画像が完全(別名:ロード)であるかどうかを確認しています。そうすれば、イベントが登録される前にイメージがロードされた場合でも、私はそれを知ることができます。イベントの後に画像がロードされない場合は、イベントがイベントを処理します。これの問題は、画像が既にロードされているかどうかを簡単に確認できることですが、代わりにエラーが発生したかどうかはわかりません。


jQueryイベントはいつ登録しますか?多分いくつかのコードが役立ちます。:)
okw 2009

たくさんのコードがありますが、上で言ったのは、私がやっていることの非常に単純なバージョンです。DOMが読み込まれた後にイベントを呼び出し、メソッドを呼び出してイベントをサムネイルに追加します。
ウィリアム

回答:


250

別のオプションは、メモリ内の画像要素を作成し、その属性を元の画像の元の属性に設定することで、onloadおよび/またはonerrorイベントをトリガーすることです。これが私の意味の例です:srcsrc

$("<img/>")
    .on('load', function() { console.log("image loaded correctly"); })
    .on('error', function() { console.log("error loading image"); })
    .attr("src", $(originalImage).attr("src"))
;

お役に立てれば!


27
期待どおりに機能していないようです。Google Chromeでは、画像がすでにキャッシュにあるときに問題が発生しているようです。load()メソッドはトリガーされません。:(
ウィリアム

4
Ugg、あなたは正しい。Chromeは間違いなく、開発が最も煩わしいブラウザです。明るいところでは、画像ソースを「」に設定してから元のソースに戻すという回避策を見つけたのではないかと思います。回答を更新します。
Xavi、

1
あなたは置くべき.attrラインを後に.loadし、.errorライン。そうしないと、これらのコールバックが追加される前に画像が読み込まれる(またはエラーが発生する)おそれがあり、それらは呼び出されません。
カラム:

19
@Xavi Chromeは、開発するのに最も煩わしいブラウザではありません。InternetExplorer 7以下で開発してみてください。$ _GETパラメータを画像の読み込みに追加するほかに、Gromixが提案するように、毎回新しい画像を読み込みます。
SSH

10
メソッド混乱や廃止、使用されていると使用とをイベントとして。.load().error().on()loaderror
Firsh-LetsWP.io 2014年

235

completenaturalWidthプロパティをこの順序で確認します。

https://stereochro.me/ideas/detecting-broken-images-js

function IsImageOk(img) {
    // During the onload event, IE correctly identifies any images that
    // weren’t downloaded as not complete. Others should too. Gecko-based
    // browsers act like NS4 in that they report this incorrectly.
    if (!img.complete) {
        return false;
    }

    // However, they do have two very useful properties: naturalWidth and
    // naturalHeight. These give the true size of the image. If it failed
    // to load, either of these should be zero.
    if (img.naturalWidth === 0) {
        return false;
    }

    // No other way of checking: assume it’s ok.
    return true;
}

1
興味深いことに、私はその投稿を以前に見ていましたが、彼らがやっていることに気づきませんでした!IEでnaturalWidthが定義されていないため、IEに対して完全です。今それをチェックするつもりです。
ウィリアム

3
どうやら、これは初めて確実に機能するだけです。次に画像のsrcを変更すると、少なくともsafariモバイルはnaturalWidthとcompleteの両方の最初の値を報告し続けます。
グルジア語2013

5
img.complete && typeof img.naturalWidth!= 'undefined' && img.naturalWidth!= 0;
エイドリアンシーリー2014年

5
@vsyncおそらくこれを1回限りのチェックとして使用し、イメージがまだロードされていない場合は、「ロード」イベントハンドラーをセットアップします。このチェックを複数回実行してCPUを叩く必要はありません。
Michael Martin-Smucker 14

2
これらの好奇心が強い人にとって、これはまさに以下にリンクされているimagesLoadedライブラリが行うこととまったく同じです。したがって、1回限りの使用法については、github.com
imagesloaded

57

要素のW3C HTML仕様についてのimg私の理解に基づいて、completenaturalHeight属性の組み合わせを使用してこれを行うことができるはずです。

function imgLoaded(imgElement) {
  return imgElement.complete && imgElement.naturalHeight !== 0;
}

complete属性の仕様から:

次のいずれかの条件に該当する場合、IDL属性completeはtrueを返す必要があります。

  • src属性は省略されます。
  • リソースがフェッチされると、ネットワークタスクソースによってキューに入れられる最後のタスクがキューに入れられます。
  • img要素は完全に利用可能です。
  • img要素が壊れています。

それ以外の場合、属性はfalseを返す必要があります。

したがって、基本的に、complete画像の読み込みが完了したか、読み込みに失敗した場合はtrueを返します。画像が正常に読み込まれた場合のみ必要なので、nauturalHeight属性もチェックする必要があります。

IDL属性naturalWidthnaturalHeight画像が利用可能であるか、あるいは0の場合、CSSピクセルで、画像の固有の幅と高さを返す必要があります。

そしてavailable、そのように定義されています:

imgは常に次のいずれかの状態です。

  • 利用不可 -ユーザーエージェントは画像データを取得していません。
  • 部分的に利用可能 -ユーザーエージェントは画像データの一部を取得しました。
  • 完全に利用可能 -ユーザーエージェントはすべての画像データを取得しており、少なくとも画像の寸法が利用可能です。
  • 壊れた -ユーザーエージェントは可能なすべての画像データを取得しましたが、画像のサイズを取得するのに十分なほど画像をデコードできません(たとえば、画像が破損しているか、形式がサポートされていないか、データを取得できませんでした) 。

img要素が部分的に利用可能な状態または完全に利用可能な状態にある場合、それは利用可能であると言われます。

したがって、イメージが「壊れている」(ロードに失敗した)場合は、使用可能な状態ではなく、壊れた状態にnaturalHeightなるため、0になります。

したがって、チェックimgElement.complete && imgElement.naturalHeight !== 0により、画像が正常に読み込まれたかどうかがわかります。

詳細については、img要素のW3C HTML仕様またはMDNを参照してください


1
画像がスタイル「コンテンツ:url」でロードされている場合、機能しません
deathangel908 '30

1
これは、ブラウザーが自然な高さ/幅を0と報告するため、SVG画像を含むFirefoxでは機能しないようです。関連するバグ:bugzilla.mozilla.org/show_bug.cgi
id

20

私は多くの異なる方法を試しました、そしてこの方法は私のために働いた唯一のものです

//check all images on the page
$('img').each(function(){
    var img = new Image();
    img.onload = function() {
        console.log($(this).attr('src') + ' - done!');
    }
    img.src = $(this).attr('src');
});

すべての画像がDOMに読み込まれ、準備ができたらトリガーされるコールバック関数を追加することもできます。これは動的に追加された画像にも適用されます。http://jsfiddle.net/kalmarsh80/nrAPk/


jsfiddleリンクが壊れている
Alex Karshin

1
上記の興味深い読み取りをテストしましたが、少数の一般的なブラウザーでキャッシュされたテストとキャッシュされていないテストの間で失敗しました。この回答は別の回答と似ていますが、今実装してテストしたものです。EdgeWin10、IE11Win8.1、Win7IE10、Win7IE9、iOS 10.2 Chrome、iOS 10.2 Safari、mac os 10.12 Chrome、mac os 10.12で動作することを確認できます。 Safari、mac os 10.12 Firefox、Google Pixel 7.1、Samsung S5 Android 4.4。addEventListener / removeEventListenerも使用することを忘れないでください:D
danjah

13

imagesLoadedJavaScriptライブラリを使用します

プレーンJavascriptとjQueryプラグインとして使用できます。

特徴:

資源


これは完璧に機能しました。function checkImages(imgs){$(imgs).each(function(){$(imgs).imagesLoaded().progress(function(instance、image){if(image.isLoaded == false){console.log(image .img.src + 'が見つかりませんでした。'); image.img.src = "/templates/img/no-image.jpg";}});}); }
Rooster242 2014年

1
それは主要なバグであるオープンな問題のトンを持っているようであり、開発者はそれらに追いついていないようです。現在のところ、これは実稼働環境ではまったく使用できません。
vsync 14年

3
@vsync未解決の問題をいくつか読みましたか?彼はそれらのほとんどすべてに対応しており、ほとんどは再現性のないエッジケースであり、他の人はほとんど遭遇していません。本番環境で問題が発生したことはありません。
Josh Harrison、

1
はい、私はそれを自分で使用し、時々それが機能しないので、それが失敗するケースをカバーするためにsetTimeoutを使用します
vsync

なぜimagesLoadedプラグインを使用したいのかには十分な理由があります。completeプロパティが明確にサポートされていないようです。ブラウザのサポートに関する信頼できる情報源が見つかりません。completeプロパティも明確な仕様を持っていないようです。HTML5仕様はそれについて言及している唯一の仕様であり、作成時にはまだドラフトバージョンです。あなたが使用している場合はnaturalWidthnaturalHeightだけではイメージがロードされているかどうかを確認するためにそれを使用する場合ので、あなたはそれが古いブラウザ上で動作させるためにいくつかの「賢い」トリックを必要とし、IE9 +をサポートしている、とあなたは行動が一貫性のあるクロスブラウザを確認する必要があります
エイドリアン2014年

8

ページの画像要素から情報を取得する
ChromeおよびFirefoxで
動作するテストjsFiddleを動作させる(コンソールを開いて結果を確認する)

$('img').each(function(){ // selecting all image element on the page

    var img = new Image($(this)); // creating image element

    img.onload = function() { // trigger if the image was loaded
        console.log($(this).attr('src') + ' - done!');
    }

    img.onerror = function() { // trigger if the image wasn't loaded
        console.log($(this).attr('src') + ' - error!');
    }

    img.onAbort = function() { // trigger if the image load was abort
        console.log($(this).attr('src') + ' - abort!');
    }

    img.src = $(this).attr('src'); // pass src to image object

    // log image attributes
    console.log(img.src);
    console.log(img.width);
    console.log(img.height);
    console.log(img.complete);

});

注:私はjQueryを使用しましたが、これは完全なJavaScriptで達成できると思いました

Iここで良い情報を見つけるOpenClassRoomを - >これはフランスのフォーラムです


3

リアルタイムネットワーク検出器-ページを 更新せずにネットワークステータスを確認します(これはjqueryではなく、テスト済みで、100%動作します(Firefox v25.0でテスト済み))。

コード:

<script>
 function ImgLoad(myobj){
   var randomNum = Math.round(Math.random() * 10000);
   var oImg=new Image;
   oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
   oImg.onload=function(){alert('Image succesfully loaded!')}
   oImg.onerror=function(){alert('No network connection or image is not available.')}
}
window.onload=ImgLoad();
</script>

<button id="reloadbtn" onclick="ImgLoad();">Again!</button>

接続が失われた場合は、[再]ボタンを押してください。

更新1: ページを更新せずに自動検出:

<script>
     function ImgLoad(myobj){
       var randomNum = Math.round(Math.random() * 10000);
       var oImg=new Image;
       oImg.src="YOUR_IMAGELINK"+"?rand="+randomNum;
       oImg.onload=function(){networkstatus_div.innerHTML="";}
       oImg.onerror=function(){networkstatus_div.innerHTML="Service is not available. Please check your Internet connection!";}
}

networkchecker = window.setInterval(function(){window.onload=ImgLoad()},1000);
</script>

<div id="networkstatus_div"></div>

100%!画像リンクがプロキシ/ファイアウォールによってブロックされている場合、または画像サーバーが応答していない場合はどうなりますか?あなたはまだネットワークが機能しています:)
Sen Jacob

これにより、サーバーからもう一度すべての画像が読み込まれ、キャッシュが(意図的に)破壊されます。つまり、チェックするだけで、すべての画像の帯域幅が(少なくとも)2倍になります。さらに、特定の場所にロードされたかどうかではなく、サーバーにイメージが存在するかどうかのみをチェックします。また、各画像がいつ読み込まれるかを知る方法もありません。
MariusBalčytis、2015年

3

このページで興味深いソリューションを読んだ後、SLaksとNoyoの投稿に非常に影響を受けた使いやすいソリューションを作成しました。これは、Chrome、IE、Firefox、Safari、およびOpera(すべてWindows)。また、私が使用したiPhone / iPadエミュレーターでも動作しました。

このソリューションとSLaksおよびNoyoの投稿の主な違いの1つは、このソリューションが主にnaturalWidthプロパティとnaturalHeightプロパティをチェックすることです。現在のブラウザバージョンでは、これらの2つのプロパティが最も役立つ一貫した結果を提供するようです。

このコードは、画像が完全に正常に読み込まれたときにTRUEを返します。画像がまだ完全に読み込まれていないか、読み込みに失敗した場合は、FALSEを返します。

注意が必要なことの1つは、画像が0x0ピクセル画像の場合、この関数はFALSEを返すことです。しかし、これらの画像は非常にまれであり、0x0ピクセルの画像がまだロードされているかどうかを確認する必要がある非常に便利なケースは考えられません:)

最初に、「isLoaded」という新しい関数をHTMLImageElementプロトタイプにアタッチして、その関数を任意の画像要素で使用できるようにします。

HTMLImageElement.prototype.isLoaded = function() {

    // See if "naturalWidth" and "naturalHeight" properties are available.
    if (typeof this.naturalWidth == 'number' && typeof this.naturalHeight == 'number')
        return !(this.naturalWidth == 0 && this.naturalHeight == 0);

    // See if "complete" property is available.
    else if (typeof this.complete == 'boolean')
        return this.complete;

    // Fallback behavior: return TRUE.
    else
        return true;

};

次に、画像の読み込みステータスを確認する必要があるときはいつでも、「isLoaded」関数を呼び出すだけです。

if (someImgElement.isLoaded()) {
    // YAY! The image loaded
}
else {
    // Image has not loaded yet
}

SLaksとNoyoの投稿に対するジョージア人のコメントによると、このソリューションは、SRC属性の変更を計画している場合、Safari Mobileでの1回限りのチェックとしてのみ使用できます。ただし、既存の画像要素のSRC属性を変更する代わりに、新しいSRC属性を使用して画像要素を作成することで、この問題を回避できます。


2

これは、上記の方法を組み合わせてクロスブラウザーで機能させる方法です(画像をdomに動的に挿入することも必要でした)。

$('#domTarget').html('<img src="" />');

var url = '/some/image/path.png';

$('#domTarget img').load(function(){}).attr('src', url).error(function() {
    if ( isIE ) {
       var thisImg = this;
       setTimeout(function() {
          if ( ! thisImg.complete ) {
             $(thisImg).attr('src', '/web/css/img/picture-broken-url.png');
          }
       },250);
    } else {
       $(this).attr('src', '/web/css/img/picture-broken-url.png');
    }
});

注:isIE変数に有効なブール状態を指定する必要があります。


2
var isImgLoaded = function(imgSelector){
  return $(imgSelector).prop("complete") && $(imgSelector).prop("naturalWidth") !== 0;
}

//またはプラグインとして

    $.fn.extend({
      isLoaded: function(){
        return this.prop("complete") && this.prop("naturalWidth") !== 0;
      }
    })

// $(".myImage").isLoaded() 

1

私が理解しているように、.completeプロパティは非標準です。普遍的ではないかもしれません... FirefoxとIEでは動作が異なるようです。いくつかの画像をJavaScriptで読み込んで、完了したかどうかを確認しています。Firefoxでは、これはうまく機能しているようです。IEでは、画像が別のスレッドでロードされているように見えるため、そうではありません。image.srcへの割り当てからimage.completeプロパティを確認するまでの間に遅延を設定した場合にのみ機能します。

また、image.onloadとimage.onerrorを使用しても機能しません。関数が呼び出されたときに、どの画像について話しているのかを知るためにパラメーターを渡す必要があるためです。同じ関数の異なるインスタンスではなく、実際には同じ関数を渡すように見えるため、どのようにしても失敗するようです。したがって、画像を識別するためにそれに渡す値は、常にループの最後の値になります。この問題を回避する方法は考えられません。

SafariとChromeでは、エラーコンソールにその画像の404が表示されている場合でも、image.complete trueとnaturalWidthが設定されているのがわかります...そして、これをテストするために意図的にその画像を削除しました。しかし、上記はFirefoxとIEでうまく機能します。


うーん、面白いですね。コード例を投稿して、いくつか試してみたいと思いませんか。
Xavi

1

このコードスニペットは、ブラウザーのキャッシュの問題を修正するのに役立ちました。

$("#my_image").on('load', function() {

    console.log("image loaded correctly"); 
}).each(function() {

     if($(this).prop('complete')) $(this).load();
});

ブラウザのキャッシュが無効になっている場合、次のコードのみが機能しません。

$("#my_image").on('load', function() {
     console.log("image loaded correctly"); 
})

それを動作させるには、追加する必要があります:

.each(function() {
     if($(this).prop('complete')) $(this).load();
});

0

このJavaScriptコードを使用して、イメージが正常にロードされたかどうかを確認できます。

document.onready = function(e) {
        var imageobj = new Image();
        imageobj.src = document.getElementById('img-id').src;
        if(!imageobj.complete){ 
            alert(imageobj.src+"  -  Not Found");
        }
}

これを試してください


0

画像とEventListenerの完全なロードに多くの問題がありました。

何を試しても、結果は信頼できませんでした。

しかし、私は解決策を見つけました。それは技術的には良いものではありませんが、今では画像の読み込みに失敗したことはありません。

私がしたこと:

                    document.getElementById(currentImgID).addEventListener("load", loadListener1);
                    document.getElementById(currentImgID).addEventListener("load", loadListener2);

                function loadListener1()
                    {
                    // Load again
                    }

                function loadListener2()
                {
                    var btn = document.getElementById("addForm_WithImage"); btn.disabled = false;
                    alert("Image loaded");
                }

イメージを1回ロードするのではなく、1回目の直後に2回ロードして、両方をイベントハンドラーを介して実行します。

私の頭痛はすべてなくなりました!


ちなみに、stackoverflowの皆さんは、私を100倍以上も助けてくれました。このため、非常に大きなありがとうございます!


0

これは私にとってはうまくいきました:)

$('.progress-image').each(function(){
    var img = new Image();
    img.onload = function() {
        let imgSrc = $(this).attr('src');
        $('.progress-image').each(function(){
            if($(this).attr('src') == imgSrc){
                console.log($(this).parent().closest('.real-pack').parent().find('.shimmer').fadeOut())
            }
        })
    }
    img.src = $(this).attr('src');
});
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.