Javascript / jQueryを使用して、画像が読み込まれたかどうかを確認するにはどうすればよいですか?


84

ユーザーのブラウザウィンドウに収まるように大きな画像のサイズを変更するJavascriptを作成しています。(残念ながら、ソース画像のサイズは制御していません。)

したがって、次のようなものがHTMLに含まれます。

<img id="photo"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

タグsrc内の画像imgがダウンロードされているかどうかを確認する方法はありますか?

$(document).ready()ブラウザが画像をロードする前に実行すると問題が発生するため、これが必要です。 $("#photo").width()そして、$("#photo").height()プレースホルダ(altテキスト)のサイズを返します。私の場合、これは134 x20のようなものです。

現在、写真の高さが150未満かどうかを確認しており、そうである場合は代替テキストであると想定しています。しかし、これはかなりのハックであり、写真の高さが150ピクセル未満の場合(私の特定のケースではありそうにない)、または代替テキストの高さが150ピクセルを超える場合(小さなブラウザウィンドウで発生する可能性があります)、破損します。 。


編集:コードを見たい人のために:

$(function()
{
  var REAL_WIDTH = $("#photo").width();
  var REAL_HEIGHT = $("#photo").height();

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(REAL_HEIGHT < 150)
    {
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
      if(REAL_HEIGHT < 150)
      {
        //image not loaded.. try again in a quarter-second
        setTimeout(adjust_photo_size, 250);
        return;
      }
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});

更新:提案をありがとう。イベントのコールバックを設定すると、イベントが発生しないリスクがある$("#photo").loadため、イメージタグで直接onLoadイベントを定義しました。記録のために、これが私が最終的に使用したコードです:

<img id="photo"
     onload="photoLoaded();"
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

次にJavascriptで:

//This must be outside $() because it may get called first
var isPhotoLoaded = false;
function photoLoaded()
{
  isPhotoLoaded = true;
}

$(function()
{
  //Hides scrollbars, so we can resize properly.  Set with JS instead of
  //  CSS so that page doesn't break with JS disabled.
  $("body").css("overflow", "hidden");

  var REAL_WIDTH = -1;
  var REAL_HEIGHT = -1;

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()
  {
    if(!isPhotoLoaded)
    {
      //image not loaded.. try again in a quarter-second
      setTimeout(adjust_photo_size, 250);
      return;
    }
    else if(REAL_WIDTH < 0)
    {
      //first time in this function since photo loaded
      REAL_WIDTH = $("#photo").width();
      REAL_HEIGHT = $("#photo").height();
    }

    var new_width = . . . ;
    var new_height = . . . ;

    $("#photo").width(Math.round(new_width));
    $("#photo").height(Math.round(new_height));
  }

});

1
これはとても古く、あなたはすでに答えを受け入れているので、ここでコメントします。jQueryプラグイン「onImagesLoad」を使用できないのはなぜですか?また、jQueryであるかどうかにかかわらず、Javascriptを使用した設定max-widthmax-height画像スタイリングの何が問題になっていますか?次に、最大幅/高さをビューポートの幅/高さのサイズに設定することにより、記述する必要のあるすべてのコードを回避します。

@ jon.wd7:私はそのプラグインに精通しておらず、2008年にはそうではなかったかもしれません。max-widthとmax-heightに関しては、次の2つがあります。1)IEではサポートされていません(IE 8についてはよくわかりません)。2)ビューポートのサイズが変更された場合(ウィンドウのサイズが変更された場合など)、最大幅/最大高さを変更するにはJavaScriptが必要です(ただし、ピクセル測定ではなく「100%」を使用した場合はそうではない場合があります)
キップ

quirksmode.orgによると、IE7とIE8で確実にサポートされています。だから私はあなたの問題がわかりません。私は個人的にこのような小さなものに対してIE6をサポートしていません。そのため、JSが有効になっていないユーザーに表示されるのと同じものが表示されます。そしてもちろん、リセットmax-widthmax-heightてサイズを変更する必要があります。しかし、それは非常に簡単な作業であり.resize()、実際にはワンライナーを使用しています。

3
完全なプロパティは、イメージがロードされているかどうかを知る必要不可欠な方法を提供します。
BorisOkunskiy 2013

1
@ Adrien、Mozillaは、Andoid(不明)を除くすべての主要なブラウザでサポートされているように完全に表示されるようになりました。
オリバーボック2015

回答:


33

イベントリスナーを追加するか、画像にonloadでアナウンスさせます。次に、そこから寸法を計算します。

<img id="photo"
     onload='loaded(this.id)'
     src="a_really_big_file.jpg"
     alt="this is some alt text"
     title="this is some title text" />

仕様によると、onloadはbody要素とframeset要素のイベントにすぎません。...私はIEでこの作品をと思うが、私はそれが他のどのブラウザで動作するかはあなたが想定することができるものであることを...私はちょうど数週間前、このに探していたことを知っていない、と述べている
ジェイソン

IE6、IE7、FF3、Opera9、Safair(Windowsベータ版)、Chrome(Windowsベータ版)でテストしました。
キップ

9
行動やコンテンツをいじることはお勧めしません。イベントは、HTMLではなくJavascriptを使用して適用する必要があります。
dionyziz 2012

10
私たちが2008年に立ち往生していないので、彼のコメントは適切です。人々はまだこれを読んでおり、08年に悪い習慣とは見なされなかったとしても、今は人々にその良い習慣を考えてほしくないでしょう。
Spoeken 2013年

3
document.querySelector( "img")。addEventListener( "load"、function(){alert( 'onload!');});
Frank Schwieterman 2013年

14

jqueryデータストアを使用して、「ロード済み」状態を定義できます。

<img id="myimage" onload="$(this).data('loaded', 'loaded');" src="lolcats.jpg" />

その後、他の場所で行うことができます:

if ($('#myimage').data('loaded')) {
    // loaded, so do stuff
}

2
特にhtmlにJavaScriptがある場合は、他のライブラリとの互換性を高めるためにjQuery(this)代わりに使用し$(this)ます(jqueryは$を所有していません)。
ジョンマグノリア2013年

11

正解は、event.special.loadを使用することです

画像がブラウザのキャッシュからロードされた場合、ロードイベントがトリガーされない可能性があります。この可能性を説明するために、イメージの準備ができたらすぐに起動する特別なロードイベントを使用できます。event.special.loadは現在、プラグインとして利用できます。

.load()のドキュメントによる


2
私はこのような提案で答えを追加するつもりでした、それをコーディングする前にこの答えを見たことがうれしいです。基本的に、ハンドラーは、ハンドラーを設定する前に、まずイメージがロードされているかどうかを確認する必要があります。すでにロードされている場合は、すぐにコールバックを起動します。それが何をするか$.readyです。幅をチェックすることを提案するつもりでしたが、それには問題があり、私はその解決策が本当に好きです。
Juan Mendes

5

Allainが言ったことを実行したいのですが、domの準備が整う前に画像が読み込まれることがあります。これは、読み込みハンドラーが起動しないことを意味します。最善の方法は、Allainが言うように行うことですが、ロードハンドラーをアタッチした後、javascriptを使用して画像のsrcを設定します。このようにして、それが発火することを保証できます。

アクセシビリティの観点から、あなたのサイトはJavaScriptを使わない人でも機能しますか?imgタグに正しいsrcを与え、jsを実行するためにdom readyハンドラーをアタッチすることをお勧めします:画像srcをクリアし(ページのちらつきを防ぐためにcssで固定され、高さを与えます)、次にimgロードハンドラーを設定します。次に、srcを正しいファイルにリセットします。このようにして、すべての拠点をカバーします:)


このサイトはJavascriptを持っていない人でも機能し、スクロールするだけですべての画像を見ることができます。
キップ

4

元の質問に対する最近のコメントの1つによる

$(function() {

  $(window).resize(adjust_photo_size);
  adjust_photo_size();

  function adjust_photo_size()  {
    if (!$("#photo").get(0).complete) {
       $("#photo").load(function() {
          adjust_photo_size();
       });
    } else {
      ... 
    }
});

警告img.completeはブラウザによって常に適切に設定されているとは限らないため、この回答はie8以下で深刻なループを引き起こす可能性があります。ie8をサポートする必要がある場合は、フラグを使用してイメージがロードされたことを記憶してください。


持て。img.completeはブラウザによって常に適切に設定されているとは限らないため、この回答はie8以下で深刻なループを引き起こす可能性があります。ie8をサポートする必要がある場合は、フラグを使用してイメージがロードされたことを記憶してください。
commonpike 2014

2

次のようなものを試してください:

$("#photo").load(function() {
    alert("Hello from Image");
});

6
ありがとう。ただし、これが発生する前にイメージがすでにロードされている可能性があります。その場合、ロードイベントは発生しません。
キップ

画像タグの直後にこのイベントを設定するスクリプトタグはどうですか?readyを使用する理由は、ドキュメント全体がロードされていることを確認するためです。この場合は不要ですよね?
Jason Goemaat 2010

2

要素の画像が読み込まれたかどうかを確認するためのクロスブラウザ互換のメソッドを提供する「imagesLoaded」と呼ばれるjQueryプラグインがあります。

サイト:https//github.com/desandro/imagesloaded/

内部に多くの画像があるコンテナの使用法:

$('container').imagesLoaded(function(){
 console.log("I loaded!");
})

プラグインは素晴らしいです:

  1. 多くの画像が入っているコンテナをチェックするために機能します
  2. imgをチェックして、ロードされているかどうかを確認するために機能します

ロードされたimgをチェックするためだけに5KBが縮小されたようです。簡単に軽量化法利用可能であるべきである...
cdalxndr

1

これについて何かコメントはありますか?

..。

doShow = function(){
  if($('#img_id').attr('complete')){
    alert('Image is loaded!');
  } else {
    window.setTimeout('doShow()',100);
  }
};

$('#img_id').attr('src','image.jpg');

doShow();

..。

どこでも動作するようです...


それは、使用に悪い習慣だsetTimeout
cdalxndr

1

jQuerys Deferred Objectを使用して画像をロードするjQuery関数を作成しました。これにより、ロード/エラーイベントに非常に簡単に対応できます。

$.fn.extend({
    loadImg: function(url, timeout) {
        // init deferred object
        var defer = $.Deferred(),
            $img = this,
            img = $img.get(0),
            timer = null;

        // define load and error events BEFORE setting the src
        // otherwise IE might fire the event before listening to it
        $img.load(function(e) {
            var that = this;
            // defer this check in order to let IE catch the right image size
            window.setTimeout(function() {
                // make sure the width and height are > 0
                ((that.width > 0 && that.height > 0) ? 
                    defer.resolveWith : 
                    defer.rejectWith)($img);
            }, 1);
        }).error(function(e) {
            defer.rejectWith($img);
        });

        // start loading the image
        img.src = url;

        // check if it's already in the cache
        if (img.complete) {
            defer.resolveWith($img);
        } else if (0 !== timeout) {
            // add a timeout, by default 15 seconds
            timer = window.setTimeout(function() {
                defer.rejectWith($img);
            }, timeout || 15000);
        }

        // return the promise of the deferred object
        return defer.promise().always(function() {
            // stop the timeout timer
            window.clearTimeout(timer);
            timer = null;
            // unbind the load and error event
            this.off("load error");
        });
    }
});

使用法:

var image = $('<img />').loadImg('http://www.google.com/intl/en_com/images/srpr/logo3w.png')
.done(function() {
    alert('image loaded');
    $('body').append(this);
}).fail(function(){
    alert('image failed');
});

http://jsfiddle.net/roberkules/AdWZj/で動作することを確認してください


それは素晴らしいと思う。コードがimg.onloadやimg.onerrorよりも望ましい場合の正確な例を教えてください。あなたのコードは、私がちょうど知らされたjQueryエラー処理の見かけの欠点を処理することだけを目的としています:ファイル拡張子がない場合、そのエラーはIEでトリガーされませんか?
mplungjan 2012年

面白いアイデア。画像がいつ完成したかを簡単に知ることができます。ただし、画像を読み込めなかった場合はどうなりますか。画像の読み込みに失敗したかどうかを知る方法を探していました。そして、あなたは私にそれをロードする際にタイムアウトのアイデアを与えました。そのため1
オーク

1
@oakタイムアウトは単なるフォールバックである必要があります。ほとんどのブラウザは、errorによって処理されるイベントを発生させる必要があります.error(function(e) { defer.rejectWith($img); })。jsFiddleを見ると、http://www.google.com/abc.png not foundテキストが結果ペインにすぐに表示されていることがわかります(エラーイベントが発生したため、タイムアウトを待機していません)
roberkules 2014

jqueryが.errorを発生させるには、2つのことが1.ハンドルである必要がありますが、エラーが発生する前に設定する必要があることに注意してください。2. .ERRORハンドルのみのhttpプロトコルではなく、ファイル://あなたがエラーを取得する文句を言わないので...
オーク

私のコード例では、成功/エラーハンドラーは、その理由でsrc属性を正確に割り当てる前に設定されます。file://制限について-ファイルプロトコルを使用して画像をリンクする必要はなく、それほど必要はないと思います。
roberkules 2014

1

この関数は、測定可能な寸法に基づいて画像がロードされているかどうかをチェックします。この手法は、一部の画像が既に読み込まれた後にスクリプトを実行する場合に役立ちます。

imageLoaded = function(node) {
    var w = 'undefined' != typeof node.clientWidth ? node.clientWidth : node.offsetWidth;
    var h = 'undefined' != typeof node.clientHeight ? node.clientHeight : node.offsetHeight;
    return w+h > 0 ? true : false;
};

この解決策では、画像に余白やパディングがなく、空の文字列の代替テキストが提供されている必要がある場合があることを発見しました。ただし、ほとんどの場合、意図したとおりに機能します。アンロードされたイメージのサイズがゼロより大きい場合にのみ失敗します。
ラルフリトック2013

1

私はこれが私のために働いたことがわかりました

document.querySelector("img").addEventListener("load", function() { alert('onload!'); });

クレジットは、受け入れられた回答にコメントしたフランク・シュヴィーターマンに完全に行きます。私はこれをここに置かなければなりませんでした、それはあまりにも価値があります...


0

多数の画像を読み込んだページを作成し、画像を読み込んだ後でのみ他の機能を実行しました。それは多くのトラフィックを生成した忙しいサイトでした。次の簡単なスクリプトは、実質的にすべてのブラウザで機能したようです。

$(elem).onload = function() {
    doSomething();
}

しかし、これはIE9の潜在的な問題です!

問題が報告された唯一のブラウザはIE9です。びっくりしませんか?この問題を解決する最善の方法は、次のように、onload関数が定義されるまでイメージにsrcを割り当てないことです。

$(elem).onload = function() {
    doSomething();
}
$(elem).attr('src','theimage.png');

IE9は時々投げないようです onload、何らかの理由でイベントを場合があるようです。このページの他の解決策(たとえば、Evan Carrollの解決策など)はまだ機能しませんでした。論理的には、ロード状態がすでに成功して関数をトリガーしたかどうかを確認し、そうでない場合は、onloadハンドラーを設定しましたが、それを行った場合でも、テストで、これら2行のjs間でイメージをロードできることを示しました。最初の行にロードされていないように見え、onloadハンドラーが設定される前にロードされます。

必要なものを取得するための最良の方法は、onloadイベントトリガーを設定するまで画像のsrcを定義しないことであることがわかりました。

IE8のサポートを最近停止したばかりなので、IE9より前のバージョンについて話すことはできません。そうしないと、サイトで使用されていた他のすべてのブラウザー(IE10と11、Firefox、Chrome、Opera、Safariなど)からです。人々が使用していたモバイルブラウザ-ハンドラーをsrc割り当てる前に設定することonloadも問題ではありませんでした。


0

純粋なCSSソリューションを完全に提案できますか?

画像を表示するDivを用意するだけです。画像を背景として設定します。次に、プロパティを持っているbackground-size: coverか、background-size: containあなたがそれをしたいかによって異なります。

cover小さい方の側面がボックスを覆うまで画像をトリミングします。 contain画像全体をdiv内に保持し、側面にスペースを残します。

以下のスニペットを確認してください。

div {
  height: 300px;
  width: 300px;
  border: 3px dashed grey;
  background-position: center;
  background-repeat: no-repeat;
}

.cover-image {
  background-size: cover;
}

.contain-image {
  background-size: contain;
}
<div class="cover-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>
<br/>
<div class="contain-image" style="background-image:url(https://assets1.ignimgs.com/2019/04/25/avengers-endgame-1280y-1556226255823_1280w.jpg)">
</div>


0

この単純な解決策が私にとって最適であることがわかりました。

        function setEqualHeight(a, b) {
            if (!$(a).height()) {
                return window.setTimeout(function(){ setEqualHeight(a, b); }, 1000);
            }
            $(b).height($(a).height());
        }

        $(document).ready(function() {
            setEqualHeight('#image', '#description');
            $(window).resize(function(){setEqualHeight('#image', '#description')});
        });
    </script>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.