画像読み込み時のjQueryコールバック(画像がキャッシュされている場合でも)


291

私はやってみたいです:

$("img").bind('load', function() {
  // do stuff
});

ただし、イメージがキャッシュから読み込まれると、loadイベントは発生しません。jQueryドキュメントはこれを修正するプラグインを提案しています、機能しません


12
あなたの質問以来、状況は変化しました。壊れたプラグインは要点に移動され、後で小さな作業プラグインjQuery.imagesLoadedを含むリポジトリに移動されました。彼らはすべての小さなブラウザの癖を修正します
Lode、

上記のJQueryライブラリは、私には問題なく動作しました。ありがとう!
2012

プラグインをありがとう、それはうまくいきました。
onimojo 2012

回答:


572

場合はsrc、すでに設定されているあなたも、バインドイベントハンドラを取得する前に、そのイベントは、キャッシュされた場合には、発射されます。これを修正するには、次の.completeように、off に基づいてイベントのチェックとトリガーをループすることができます。

$("img").one("load", function() {
  // do stuff
}).each(function() {
  if(this.complete) {
      $(this).load(); // For jQuery < 3.0 
      // $(this).trigger('load'); // For jQuery >= 3.0 
  }
});

から.bind()への変更に注意し.one()て、イベントハンドラが2回実行されないようにしてください。


8
あなたのソリューションは私にとって完璧に機能しましたが、このコード「if(this.complete)」が実行されるとき、画像コンテンツがロードされた後、またはその前に何かを理解したいと思いますか?私はこの.eachから理解できるように、すべての$( "img")でループしているため、画像コンテンツが空であり、ロードが発生しない可能性があるためです。うーん、私は何か足りないところがあると思います、それをよりよく理解するために起こっていることを説明できればいいでしょう。ありがとう。
Amr Elgarhy、2011年

33
答えが変わったので。今そこにあるプラグインの小さな作業jQuery.imagesLoadedが。彼らはすべての小さなブラウザの癖を修正します
Lode、

3
setTimeout(function(){//do stuff},0)'load'関数内にを追加します。0を指定すると、ブラウザーシステム(DOM)に1ティックが追加され、すべてが適切に更新されるようになります。
dsdsdsdsd 2013

14
@Lode-それは巨大なプラグインであり、どんな規模でも決して小さくはありません!!
vsync

5
JQuery 3メソッド.load()はイベントをトリガーせず、1つの必須引数があるため、.trigger("load")代わりに使用します
ForceUser

48

DOM以外の画像オブジェクトに再読み込みすることを提案できますか?キャッシュされている場合、これにはまったく時間がかからず、onloadは引き続き起動します。キャッシュされていない場合は、画像が読み込まれるときにonloadを起動します。これは、画像のDOMバージョンの読み込みが完了するのと同時に行う必要があります。

JavaScript:

$(document).ready(function() {
    var tmpImg = new Image() ;
    tmpImg.src = $('#img').attr('src') ;
    tmpImg.onload = function() {
        // Run onload code.
    } ;
}) ;

更新(複数の画像を処理し、正しい順序でonload添付ファイルを添付):

$(document).ready(function() {
    var imageLoaded = function() {
        // Run onload code.
    }
    $('#img').each(function() {
        var tmpImg = new Image() ;
        tmpImg.onload = imageLoaded ;
        tmpImg.src = $(this).attr('src') ;
    }) ;
}) ;

1
追加する前loadハンドラーをアタッチするようにしてください。これも機能しませんが、1つのイメージの場合、OPsコードは多くの場合に機能します:)
Nick Craver

おかげで、私はこれらの2つの問題に対処できると期待する更新バージョンを追加しました。
Gus

#img要素セレクターではないIDです:)また、this.src機能します。不要な場所でjQueryを使用する必要はありません。
Nick Craver

$( 'img')である必要があります。しかし、ソリューションは2k15でもgr8です
Dimag Kharab '22

また、複数画像の場合、の各画像のDOM要素を操作する場合は、imageLoadedtmp.onload = imageLoaded.bind(this)
blisstdev

38

私の簡単な解決策は、外部プラグインを必要とせず、一般的なケースでは十分です:

/**
 * Trigger a callback when the selected images are loaded:
 * @param {String} selector
 * @param {Function} callback
  */
var onImgLoad = function(selector, callback){
    $(selector).each(function(){
        if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
            callback.apply(this);
        }
        else {
            $(this).on('load', function(){
                callback.apply(this);
            });
        }
    });
};

次のように使用します。

onImgLoad('img', function(){
    // do stuff
});

たとえば、ロード時に画像をフェードインするには、次のようにします。

$('img').hide();
onImgLoad('img', function(){
    $(this).fadeIn(700);
});

あるいは、jqueryプラグインのようなアプローチを好む場合:

/**
 * Trigger a callback when 'this' image is loaded:
 * @param {Function} callback
 */
(function($){
    $.fn.imgLoad = function(callback) {
        return this.each(function() {
            if (callback) {
                if (this.complete || /*for IE 10-*/ $(this).height() > 0) {
                    callback.apply(this);
                }
                else {
                    $(this).on('load', function(){
                        callback.apply(this);
                    });
                }
            }
        });
    };
})(jQuery);

次のように使用します。

$('img').imgLoad(function(){
    // do stuff
});

例えば:

$('img').hide().imgLoad(function(){
    $(this).fadeIn(700);
});

urm ..そして私の画像にcssで設定されたサイズがある場合はどうなりますか?
Simon_Weaver 2014

を設定しwidth、のmax-heightままheight:autoにします。多くの場合、画像をストレッチする必要がある場合にのみ、幅と高さの両方を設定する必要があります。より堅牢なソリューションを実現するには、ImagesLoadedの
guari

1
はい、タイプミスでした。jsdocは問題ありませんでした。行の例を修正しました
guari

1
$ .fn.imgLoadを使用したこのソリューションは、ブラウザー間で機能します。&& / * for IE 10-* / this.naturalHeight> 0この行は、imgをブロックできるが高さがあるため、CSSスタイルを考慮しません。IE10での作業
Patryk Padus

1
これには(小さな)競合状態があります。画像はスクリプトとは別のスレッドでロードされる可能性があるため、完了の確認とonloadイベントのアタッチの間でロードできます。この場合、何も起こりません。通常、JSはレンダリングと同期しているため、競合状態を心配する必要はありませんが、これは例外です。 html.spec.whatwg.org/multipage/...
Mog0

23

あなたは本当にそれをjQueryで行う必要がありますか?onloadイベントを画像に直接添付することもできます。

<img src="/path/to/image.jpg" onload="doStuff(this);" />

キャッシュからであってもなくても、画像が読み込まれるたびに起動します。


5
インラインJavaScriptを使用しないほうがきれいです
hazelnut

1
こんにちは、ビョルン、onload画像がキャッシュから2回目に読み込まれたときにハンドラーが起動しますか?
SexyBeast 2014年

1
@Cupidvogelいいえそれはしません。
2015年

3
おい、あなたは私の命を救った、私は少なくとも他の12の解決策を試しました、そしてあなたのものは実際に働いた唯一のものです。私は真剣に考えて、あなたの回答をさらに10回投票するためにさらに10個のアカウントを作成することを考えています。本当にありがとう!
カルロ

1
私はインラインJSに対する人々の嫌悪感を理解したことがありません。画像の読み込みは、残りのページ読み込みプロセスとは別に、順番どおりに行われません。したがって、これは画像の読み込み完了に関するフィードバックを即座に得る唯一の有効なソリューションです。ただし、誰かがjQueryが読み込まれるのを待つ必要があり、それが後で発生する場合は、ここで単純なソリューションを使用せずに、他のソリューションの1つを使用する必要があります(Piotrは疑似に依存しないため、おそらく最良のオプションです。ハッキングしますが、guariのheight()チェックも重要かもしれません)。処理キューも役立ちます。
CubicleSoft 2017年

16

読み込みエラーをサポートするこのコードを使用することもできます:

$("img").on('load', function() {
  // do stuff on success
})
.on('error', function() {
  // do stuff on smth wrong (error 404, etc.)
})
.each(function() {
    if(this.complete) {
      $(this).load();
    } else if(this.error) {
      $(this).error();
    }
});

1
これは私にとって最もうまくいきました。load最初にハンドラを設定してから、後でeach関数でそれを呼び出すことが重要だと思います。
GreenRaccoon23

以下のコードを使用して画像を設定する '' var img = new Image(); img.src = sosImgURL; $(img).on( "load"、function(){''
imdadhusen

13

私は自分自身でこの問題を抱えていて、キャッシュを殺したりプラグインをダウンロードしたりすることを含まない解決策をどこでも探しました。

私はこのスレッドをすぐには見ていなかったので、代わりに興味深い修正である何かを見つけました(ここに投稿する価値があると思います)。

$('.image').load(function(){
    // stuff
}).attr('src', 'new_src');

私は実際にここのコメントからこのアイデアを得ました:http : //www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

なぜ機能するのかはわかりませんが、IE7でテストしたところ、機能する前にどこで問題が発生しましたか。

それが役に立てば幸い、

編集する

受け入れられた答えは実際に理由を説明しています:

srcがすでに設定されている場合、イベントハンドラーがバインドされる前に、ケース内のキャッシュでイベントが発生しています。


4
私はこれを多くのブラウザでテストしましたが、どこでも失敗することはありませんでした。$image.load(function(){ something(); }).attr('src', $image.attr('src'));元のソースをリセットするために使用しました。
モーリス

私は、このアプローチがiOSでは機能しないことを発見しました。少なくともSafari / 601.1とSafari / 602.1の場合
cronfyしてください。

なぜそれがどのブラウザに含まれているのかを知るのは素晴らしいでしょう
Sammaye 2017

5

jQueryを使用して画像のsrcで新しい画像を生成し、それにロードメソッドを直接割り当てることにより、jQueryが新しい画像の生成を完了したときにloadメソッドが正常に呼び出されます。これはIE 8、9、10で私のために働いています

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});

Ruby on Railsを使用していて、リモートリクエストで__rjs.erbテンプレートを使用している場合、これが私が見つけた唯一のソリューションです。js.erbでパーシャルを使用しているため、バインディングが失われます($( "#img" .on( "load")...)。また、画像の場合、 "on"メソッドを委任することはできません:$( "body")。 on( "load"、 "#img"、function()...
AlbertCatalà'27 / 01/16

5

私が見つけた解決策https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (このコードはコメントから直接取得されました)

var photo = document.getElementById('image_id');
var img = new Image();
img.addEventListener('load', myFunction, false);
img.src = 'http://newimgsource.jpg';
photo.src = img.src;

これはまさに私が探していたものです。サーバーから1つの画像が届きます。私はそれをプリロードしてから提供したかったのです。多くの回答のようにすべての画像を選択するのではありません。いいね。
Kai Qing

4

GUSの例の変更:

$(document).ready(function() {
    var tmpImg = new Image() ;
    tmpImg.onload = function() {
        // Run onload code.
    } ;

tmpImg.src = $('#img').attr('src');
})

onloadの前後にソースを設定します。


@Gusの回答と同様に、これは複数の画像では機能しません... ハンドラーをsrcアタッチする前にを設定する必要onloadはありません。その後で十分です。
Nick Craver

3

imgオブジェクトが定義された後、src引数を別の行に再度追加するだけです。これはIEをだましてlad-eventをトリガーさせます。醜いですが、これは私がこれまでに見つけた最も簡単な回避策です。

jQuery('<img/>', {
    src: url,
    id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE

1

あなたがこのようにしたいのであれば、私はあなたに小さなヒントを与えることができます:

<div style="position:relative;width:100px;height:100px">
     <img src="loading.jpg" style='position:absolute;width:100px;height:100px;z-index:0'/>
     <img onLoad="$(this).fadeIn('normal').siblings('img').fadeOut('normal')" src="picture.jpg" style="display:none;position:absolute;width:100px;height:100px;z-index:1"/>
</div>

ブラウザが画像をキャッシュするときにこれを行うと、常にimgが表示されますが、実際の画像の下でimgをロードすることは問題ありません。


1

e.target.widthが未定義になるIEでこの問題が発生しました。loadイベントが発生しましたが、IEで画像のサイズを取得できませんでした(chrome + FFは機能しました)。

e.currentTarget.naturalWidthe.currentTarget.naturalHeightを探す必要があることがわかりました

ここでも、IEは独自の(より複雑な)方法で処理を実行します。


0

JAILプラグインを使用して問題を解決できます。これにより、画像の遅延読み込み(ページのパフォーマンスの向上)が可能になり、コールバックをパラメーターとして渡すことができます。

$('img').asynchImageLoader({callback : function(){...}});

HTMLは次のようになります。

<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />

0

純粋なCSSソリューションが必要な場合、このトリックは非常にうまく機能します。変換オブジェクトを使用してください。これは、画像がキャッシュされているかどうかに関係なく機能します。

CSS:

.main_container{
    position: relative;
    width: 500px;
    height: 300px;
    background-color: #cccccc;
}

.center_horizontally{
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: green;
  left: 50%;
  top: 0;
  transform: translate(-50%,0);
}

.center_vertically{
  position: absolute;
  top: 50%;
  left: 0;
  width: 100px;
  height: 100px;
  background-color: blue;
  transform: translate(0,-50%);
}

.center{
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100px;
  height: 100px;
  background-color: red;
  transform: translate(-50%,-50%);
}

HTML:

<div class="main_container">
  <div class="center_horizontally"></div>
  <div class="center_vertically"></div>
  <div class="center"></div>
  </div>
</div

コードペンの例

Codepen LESSの例


これが画像の読み込みでどのように機能するかの例を挙げていただけますか?
Hastig Zusammenstellen 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.