छवि लोड पर jQuery कॉलबैक (भले ही छवि कैश की गई हो)


291

मैं करना चाहता हूँ:

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

जब छवि को कैश से लोड किया जाता है तो लोड ईवेंट आग नहीं करता है। JQuery डॉक्स इसे ठीक करने के लिए एक प्लगइन का सुझाव देता है , लेकिन यह काम नहीं करता है


12
जब से आपके सवाल बदले हैं। टूटे हुए प्लगइन को एक जिस्ट में ले जाया गया और बाद में एक छोटे से काम करने वाले प्लगइन jQuery.imagesLoaded के साथ एक रेपो में लाया गया । वे सभी छोटे ब्राउज़र quirks को ठीक करते हैं ।
परत

ऊपर उल्लेख JQuery पुस्तकालय मेरे लिए ठीक काम किया। धन्यवाद!
१२:४२

प्लगइन के लिए धन्यवाद, यह ठीक काम किया।
onimojo

जवाबों:


572

यदि srcपहले से सेट है, तो ईवेंट कैश किए गए मामले में फायरिंग कर रहा है, इससे पहले कि आप इवेंट हैंडलर को बाध्य भी करें। इसे ठीक करने के लिए, आप .completeइस तरह से ईवेंट के आधार पर जाँच और ट्रिगर कर सकते हैं :

$("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()इतना ईवेंट हैंडलर दो बार नहीं चलता है।


8
आपके समाधान ने मेरे लिए एकदम सही काम किया, लेकिन मैं कुछ समझना चाहता हूं, जब यह कोड "अगर (यह। पूर्ण)" चलेगा, तो छवि सामग्री लोड होने से पहले या उससे पहले? क्योंकि जैसा कि मैं इस से समझ सकता हूँ कि आप सभी $ ("img") पर लूप कर रहे हैं और हो सकता है कि छवि सामग्री खाली हो और लोड नहीं होगा। हम्म्म्म, मुझे लगता है कि मुझे कुछ याद आ रहा है, यह अच्छा होगा यदि आप यह वर्णन कर सकते हैं कि इसे बेहतर समझने के लिए चल रहा है। धन्यवाद।
अमर एल्गरहि

33
जब से आपके उत्तर की चीजें बदली हैं। अब एक छोटा सा काम करने वाला प्लगइन है jQuery.imagesLoaded । वे सभी छोटे ब्राउज़र quirks को ठीक करते हैं ।
परत

3
मैं setTimeout(function(){//do stuff},0)'लोड' फ़ंक्शन के भीतर जोड़ूंगा ... 0 ब्राउज़र सिस्टम (DOM) को एक अतिरिक्त टिक देता है ताकि यह सुनिश्चित हो सके कि सब कुछ ठीक से अपडेट किया गया है।
dsdsdsdsd

14
@ लॉड - यह एक विशाल प्लगइन है, किसी भी पैमाने पर बिल्कुल भी छोटा नहीं है !!
vsync

5
चूँकि JQuery की 3 विधि .load()ईवेंट को ट्रिगर नहीं करती है और इसमें 1 आवश्यक तर्क है, .trigger("load")इसके बजाय का उपयोग करें
ForceUser

48

क्या मैं यह सुझाव दे सकता हूं कि आप इसे गैर-डोम छवि ऑब्जेक्ट में पुनः लोड करें? यदि इसे कैश किया जाता है, तो इसमें बिल्कुल भी समय नहीं लगेगा और ऑनलोड अभी भी चालू रहेगा। यदि इसे कैश नहीं किया जाता है, तो छवि लोड होने पर यह ऑनलोड को आग देगा, जो उसी समय होना चाहिए जब छवि का डोम संस्करण लोड हो रहा है।

जावास्क्रिप्ट:

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

अद्यतन (कई छवियों को संभालने के लिए और सही ढंग से लोड किए गए अनुलग्नक के साथ):

$(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हैंडलर से पहले यह जोड़ा है, भी इस काम नहीं करेगा, लेकिन एक छवि के लिए, कई के लिए :) ऑप्स कोड काम करता है
निक Craver

धन्यवाद, मैंने एक अद्यतन संस्करण जोड़ा है जो मुझे आशा है कि इन दो मुद्दों को संबोधित करेगा।
गूस

#imgएक आईडी नहीं एक तत्व चयनकर्ता है :) यह भी this.srcकाम करता है, जहां यह आवश्यक नहीं है वहां jQuery का उपयोग करने की कोई आवश्यकता नहीं है :) लेकिन एक और छवि बनाने से ऐसा लगता है कि या तो मामले में IMO।
निक Craver

यह $ ('img') होना चाहिए। लेकिन समाधान 2k15 में भी gr8 है
दिमाग खब

इसके अलावा, कई छवि मामले के लिए, आप में प्रत्येक छवि के लिए डोम तत्व पर काम करना चाहते हैं imageLoaded, तो का उपयोगtmp.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

सेट करें width, max-heightऔर छोड़ दें height:auto, अक्सर यह चौड़ाई और ऊंचाई दोनों को सेट करने के लिए आवश्यक है यदि आपको छवि को फैलाने की आवश्यकता है; एक और अधिक मजबूत समाधान के लिए मैं ImagesLaded
guari

1
हाँ, यह गलत था, jsdoc ठीक था, मैंने लाइन उदाहरण को सही किया
ग्वारी

1
$ .Fn.imgLoad के साथ यह समाधान ब्राउज़र में काम करता है। इसे ठीक करना और भी बेहतर होगा: && / * IE 10 के लिए - * / this.naturalHeight> 0 यह लाइन css स्टाइल को ध्यान में नहीं रखेगी क्योंकि img को ब्लॉक किया जा सकता है लेकिन इसकी ऊंचाई है। IE10 में काम करें
पैट्रिक पेकस

1
यह एक छोटी (छोटी) दौड़ की स्थिति है। छवि को स्क्रिप्ट में एक अलग थ्रेड में लोड किया जा सकता है और इसलिए लोड की पूरी और चेक अटैच करने की स्थिति के बीच लोड हो सकता है, जिस स्थिति में कुछ भी नहीं होगा। आम तौर पर जेएस प्रतिपादन के साथ तुल्यकालिक है और इसलिए आपको दौड़ की स्थिति के बारे में चिंता करने की ज़रूरत नहीं है लेकिन यह एक अपवाद है। html.spec.whatwg.org/multipage/…
मोग ०

23

क्या आपको वास्तव में इसे jQuery के साथ करना है? आप onloadअपनी छवि पर सीधे घटना को संलग्न कर सकते हैं ;

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

यह हर बार छवि को लोड करेगा, कैश से या नहीं।


5
यह इनलाइन जावास्क्रिप्ट के बिना क्लीनर है
हेज़लनट

1
हाय, ब्योर्न, onloadजब छवि को दूसरी बार कैश से लोड किया जाता है तो क्या हैंडलर फायर करेगा ?
सेक्सीबीट

1
@Cupidvogel नहीं यह नहीं होगा।
विज्ञापन

3
यार, तुमने मेरी जान बचाई है, मैंने कम से कम एक दर्जन अन्य समाधानों की कोशिश की है और तुम्हारा केवल एक ही है जो वास्तव में काम करता है। मैं 10 से अधिक बार अपना जवाब देने के लिए 10 और खाते बनाने के बारे में गंभीरता से सोच रहा हूं। गंभीरता से धन्यवाद!
कार्लो

1
मैं कभी भी लोगों की नाराजगी को इनसाइड JS नहीं समझ पाया। शेष पेज लोडिंग प्रक्रिया से इमेज लोडिंग अलग से और अनुक्रम से बाहर होती है। इसलिए, छवि लोडिंग पूर्ण होने के बारे में तत्काल प्रतिक्रिया प्राप्त करने के लिए यह एकमात्र वैध समाधान है। हालांकि, अगर किसी को लोड करने के लिए jQuery का इंतजार करना होगा और बाद में ऐसा होगा, तो उन्हें यहां सरल समाधान का उपयोग नहीं करना होगा और अन्य समाधानों में से एक का उपयोग करना होगा (Piotr's शायद सबसे अच्छा विकल्प है क्योंकि यह छद्म पर निर्भर नहीं है- हैक्स लेकिन ग्वारी की ऊंचाई () चेक महत्वपूर्ण भी हो सकती है)। एक प्रसंस्करण कतार उपयोगी भी हो सकती है।
क्यूबिकलसॉफ्ट

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फ़ंक्शन में कॉल करना है।
ग्रीनरीकोन

नीचे दिए गए कोड '' var img = new Image () का उपयोग करके छवि सेट करना; img.src = sosImgURL; $ (img) .on ("लोड", फ़ंक्शन () {''
imdadhusen

13

मेरे पास बस यह समस्या थी, हर जगह एक समाधान के लिए खोज की गई जिसमें मेरे कैश को मारने या प्लगइन डाउनलोड करना शामिल नहीं था।

मैंने इस धागे को तुरंत नहीं देखा, इसलिए मुझे इसके बजाय कुछ और मिला, जो एक दिलचस्प फिक्स है और (मुझे लगता है) यहां पोस्ट करने के योग्य है:

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

मुझे वास्तव में यहाँ टिप्पणियों से यह विचार मिला: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-use-jquery/

मुझे नहीं पता कि यह क्यों काम करता है, लेकिन मैंने IE7 पर इसका परीक्षण किया है और अब यह काम करने से पहले टूट गया।

आशा करता हूँ की ये काम करेगा,

संपादित करें

स्वीकृत उत्तर वास्तव में बताते हैं कि क्यों:

यदि src पहले से सेट है, तो इवेंट हैंडलर बाउंड होने से पहले इवेंट कैश में फायरिंग कर रहा है।


4
मैंने परीक्षण किया है कि यह बहुत सारे ब्राउज़रों में है और कहीं भी यह विफल नहीं पाया गया है। मैं $image.load(function(){ something(); }).attr('src', $image.attr('src'));मूल स्रोत को रीसेट करता था।
मौरिस

मैंने पाया है कि यह दृष्टिकोण iOS पर काम नहीं करता है, कम से कम सफारी / 601.1 और सफारी / 602.1 के लिए
cronfy

यह पता लगाने के लिए भयानक होगा कि यह किस ब्राउज़र में है?
सम्मेय

5

छवि के src के साथ एक नई छवि उत्पन्न करने के लिए jQuery का उपयोग करके, और लोड विधि को सीधे उस पर असाइन करते हुए, लोड विधि को सफलतापूर्वक कहा जाता है जब jQuery नई छवि उत्पन्न करता है। यह IE 8, 9 और 10 में मेरे लिए काम कर रहा है

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

उन लोगों के लिए जो दूरस्थ अनुरोध के साथ, __rjs.erb टेम्प्लेट का उपयोग करके रूबी ऑन रेल का उपयोग करते हैं, यह एकमात्र समाधान है जो मैंने पाया है। क्योंकि js.erb में partials का उपयोग करते हुए, यह de बाइंडिंग खो देता है ($ ("# img" .on ("load") ... और छवियों के लिए "on" विधि: $ ("बॉडी") को प्रत्यायोजित करना संभव नहीं है। on ("लोड", "# img", फंक्शन () ...
अल्बर्ट कैटेलै

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;

यही वह है जिसकी तलाश में मैं हूं। सर्वर से मेरे पास एक एकल छवि आती है। मैं इसे प्रीलोड करना चाहता था और फिर सेवा करना चाहता था। सभी छवियों का चयन नहीं करना जैसे कई उत्तर करते हैं। अच्छा था।
काई किंग

4

GUS के उदाहरण में संशोधन:

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

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

ऑनलोड से पहले और बाद में स्रोत सेट करें।


@ गस के जवाब की तरह, यह कई छवियों के लिए काम नहीं करेगा ... और हैंडलर srcसंलग्न करने से पहले सेट करने की आवश्यकता नहीं है onload, एक बार बाद में पर्याप्त होगा।
निक Craver

3

बस एक अलग लाइन पर src तर्क को फिर से जोड़ें के बाद img oject परिभाषित किया गया है। यह IE को लैड-इवेंट को ट्रिगर करने में धोखा देगा। यह बदसूरत है, लेकिन यह अब तक मुझे मिला सबसे सरल वर्कअराउंड है।

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>

यदि आप ऐसा करते हैं कि जब ब्राउज़र चित्रों को कैश करता है, तो यह कोई समस्या नहीं है हमेशा दिखाया गया है लेकिन वास्तविक चित्र के तहत आईएमजी लोड हो रहा है।


1

मैं IE के साथ यह समस्या थी जहाँ e.target.width अपरिभाषित होगा। लोड घटना में आग लग जाएगी लेकिन मैं IE में छवि के आयाम नहीं प्राप्त कर सका (क्रोम + एफएफ ने काम किया)।

पता चलता है कि आप e.currentTarget.naturalWidth और e.currentTarget.naturalHight को देखना चाहते हैं

एक बार फिर, आईई चीजों को अपने ही (अधिक जटिल) तरीके से करता है।


0

आप JAIL प्लगइन का उपयोग करके अपनी समस्या को हल कर सकते हैं जो आपको आलसी लोड छवियों (पृष्ठ प्रदर्शन में सुधार) और कॉलबैक को पैरामीटर के रूप में पारित करने की अनुमति देता है

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

HTML जैसा दिखना चाहिए

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

0

यदि आप एक शुद्ध सीएसएस समाधान चाहते हैं, तो यह ट्रिक बहुत अच्छी तरह से काम करती है - ट्रांसफॉर्म ऑब्जेक्ट का उपयोग करें। कैश होने या न होने पर भी यह चित्रों के साथ काम करता है:

सीएसएस:

.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

कोडपेन उदाहरण

कोडपैन कम उदाहरण


क्या आप एक उदाहरण दे सकते हैं कि यह इमेज लोडिंग के साथ कैसे काम करता है?
हास्टिग ज़ुसमेनस्टेलन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.