web-dev-qa-db-ja.com

Javascript / jQueryを使用して、イメージがロードされたかどうかを確認するにはどうすればよいですか?

ユーザーのブラウザウィンドウに収まるように大きな画像のサイズを変更する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()は、プレースホルダー(代替テキスト)のサイズを返します。私の場合、これは134 x 20のようなものです。

今は、写真の高さが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));
  }

});
_
83
Kip

イベントリスナーを追加するか、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" />

jquery data store を使用すると、「ロード済み」状態を定義できます。

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

その後、他の場所でできること:

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

正しい答えは、 event.special.load を使用することです

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

。load() のドキュメントに従って

9
Evan Carroll

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

アクセシビリティの観点から、あなたのサイトはjavascriptのない人々のためにまだ機能しますか? imgタグに正しいsrcを指定し、dom readyハンドラーをアタッチしてjsを実行します:画像srcをクリアし(CSSで固定し、高さを指定してページのちらつきを防ぎます)、次にimgロードハンドラーを設定します。次に、srcを正しいファイルにリセットします。この方法で、すべてのベースをカバーできます:)

5
Andrew Bullock

元の質問に対する最近のコメントの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をサポートする必要がある場合は、フラグを使用して、イメージがロードされたことを記憶してください。

4
commonpike

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

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

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

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

クレジットは、受け入れられた回答についてコメントしたフランク・シュウィーターマンに全面的に委ねられています。私はこれをここに置かなければなりませんでした、それはあまりにも貴重です...

2
Armand

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

...

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

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

doShow();

...

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

2
Jay

「imagesLoaded」と呼ばれるjQueryプラグインがあります。これは、要素のイメージがロードされているかどうかを確認するためのクロスブラウザ互換のメソッドを提供します。

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

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

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

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

  1. 内部に多くの画像があるコンテナをチェックするために動作します
  2. imgをチェックして、ロードされたかどうかを確認します
2
jay

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/

1
roberkules

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

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;
};
1
Ralph Ritoch

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

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

ただし、これはIS IE9の潜在的な問題!

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

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

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

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

私たちは最近IE8のサポートをやめたばかりなので、IE9以前のバージョンについては話すことができません。モバイルブラウザーの人々が使用していた-srcハンドラーを割り当てる前にonloadを設定することも問題ではありませんでした。

0
Octopus

純粋な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
arunwithasmile