Обратный вызов jQuery при загрузке изображения (даже когда изображение кэшируется) - PullRequest
274 голосов
/ 07 октября 2010

Я хочу сделать:

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

Но событие загрузки не запускается, когда изображение загружается из кэша. Документы jQuery предлагают плагин , чтобы исправить это, но не работает

Ответы [ 14 ]

551 голосов
/ 07 октября 2010

Если 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(), поэтому обработчик событий не запускается дважды.

43 голосов
/ 07 октября 2010

Могу ли я предложить вам перезагрузить его в объект изображения не из DOM? Если он кешируется, это совсем не займет времени, а нагрузка все равно сработает. Если он не кэшируется, он будет запускать загрузку при загрузке изображения, что должно быть одновременно с завершением загрузки DOM-версии образа.

Javascript:

$(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') ;
    }) ;
}) ;
35 голосов
/ 03 декабря 2013

Мое простое решение, ему не нужен внешний плагин, и для общих случаев должно быть достаточно:

/**
 * 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);
});
22 голосов
/ 07 октября 2010

Вам действительно нужно делать это с jQuery? Вы также можете прикрепить событие onload непосредственно к вашему изображению;

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

Он будет срабатывать каждый раз, когда изображение загружено, из кэша или нет.

15 голосов
/ 20 марта 2014

Вы также можете использовать этот код с поддержкой ошибки загрузки:

$("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();
    }
});
13 голосов
/ 13 декабря 2012

У меня просто была эта проблема, я всюду искал решение, которое не включало бы уничтожение моего кэша или загрузку плагина.

Я не видел эту ветку сразу, поэтому вместо этого я нашел кое-что интересное, и (я думаю) заслуживающее публикации здесь:

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

Я на самом деле получил эту идею из комментариев здесь: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/

Я понятия не имею, почему это работает, но я проверил это на IE7 и где он сломался, прежде чем теперь работает.

Надеюсь, это поможет,

Редактировать

Принятый ответ фактически объясняет, почему:

Если src уже установлен, то событие запускается в кеше, перед тем как вы получите привязку обработчика события.

5 голосов
/ 22 июня 2017

Решение, которое я нашел 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 голосов
/ 24 июня 2013

Используя jQuery для генерации нового изображения с помощью src изображения и назначая непосредственно для него метод загрузки, метод загрузки успешно вызывается, когда jQuery завершает генерацию нового изображения.Это работает для меня в IE 8, 9 и 10

$('<img />', {
    "src": $("#img").attr("src")
}).load(function(){
    // Do something
});
4 голосов
/ 07 октября 2010

Модификация примера GUS:

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

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

Установить источник до и после загрузки.

3 голосов
/ 14 ноября 2013

Просто повторно добавьте аргумент src в отдельной строке после определения img oject.Это обманом заставит IE запустить лад-событие.Это уродливо, но это самый простой обходной путь, который я нашел до сих пор.

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