jQuery Callback на нагрузке изображений (даже когда изображение кэшируется)

StackOverflow https://stackoverflow.com/questions/3877027

Вопрос

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

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

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

Это было полезно?

Решение

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

Другие советы

Могу ли я предложить, чтобы вы перезагрузили его в объект Image Image? Если это кэшируется, это не займет время вообще, и нагрузка все еще будет огонь. Если это не кэшируется, он будет выстрелить нагрузку, когда изображение загружено, что должно быть то же время, что и версия 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') ;
    }) ;
}) ;

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

/**
 * 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);
});

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

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

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

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

$("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();
    }
});

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

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

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

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

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

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

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

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

Если SRC уже устанавливается, то событие выпускается в кэш Counded, прежде чем получить границу обработчика события.

Решение, которое я нашел 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;

Модификация пример Гуса:

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

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

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

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

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

Просто повторно добавьте аргумент SRC на отдельной строке после определения ввода IMG. Это будет трюк, т.е. вводит запуск мероприятия. Это уродливо, но это самый простой обходной путь, который я нашел до сих пор.

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

Я могу дать вам немного совет, если вы хотите, подобно этому:

<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 под реальную картину.

У меня была эта проблема с IE, где e.ctarget.width будет неопределенным. Событие нагрузки будет стрелять, но я не мог получить размеры изображения в IE (работал Chrome + FF).

Оказывается, вам нужно искать E.currentTarget.naturalwidth & E.currentTarget.naturalheight.naturalHeight..

Еще раз, то есть делает вещи своими (более сложными) способ.

Вы можете решить вашу проблему, используя ТЮРЬМА плагин, который также позволяет вам ленивать изображения (улучшение производительности страницы) и передача Перезвоните как параметр

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

HTML должен выглядеть как

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

Если вы хотите чистое решение 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

Пример кодепена

Кодепен Менее примера

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top