Я хочу делать:
$("img").bind('load', function() {
// do stuff
});
Но событие загрузки не срабатывает, когда изображение загружается из кэша. Документы jQuery предлагают плагин, чтобы это исправить, но он не работает
Я хочу делать:
$("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()
чтобы обработчик событий не запускался дважды.
setTimeout(function(){//do stuff},0)
'load' ... 0 дает системе браузера (DOM) один дополнительный тик, чтобы убедиться, что все правильно обновлено.
.load()
не вызывает событие и имеет 1 обязательный аргумент, используйте .trigger("load")
вместо него
Могу ли я предложить вам перезагрузить его в объект изображения не из 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') ;
}) ;
}) ;
load
обработчик до того, как он будет добавлен, также это не будет работать, но для одного изображения код OPs работает для многих :)
#img
является идентификатором, а не селектором элемента :) Также this.src
работает, нет необходимости использовать jQuery там, где он не нужен :) Но создание другого изображения кажется избыточным в любом случае IMO.
imageLoaded
, то используйтеtmp.onload = imageLoaded.bind(this)
Мое простое решение, для него не нужен внешний плагин и для общих случаев должно быть достаточно:
/**
* 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);
});
width
, max-height
и отпуск height:auto
, часто необходимо установить как ширину и высоту , только если вам нужно , чтобы растянуть изображение; для более надежного решения я бы использовал плагин, такой как ImagesLoaded
Вы действительно должны сделать это с JQuery? Вы можете прикрепить onload
событие непосредственно к вашему изображению;
<img src="/path/to/image.jpg" onload="doStuff(this);" />
Он будет срабатывать каждый раз, когда изображение загружено, из кэша или нет.
onload
обработчик срабатывать при повторной загрузке изображения из кэша?
Вы также можете использовать этот код с поддержкой ошибки загрузки:
$("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();
}
});
load
сначала установить обработчик, а затем вызвать его позже в each
функции.
У меня просто была эта проблема, я всюду искал решение, которое не включало бы уничтожение моего кэша или загрузку плагина.
Я не видел эту ветку сразу, поэтому нашел что-то еще, что является интересным исправлением и (я думаю) достойным публикации здесь:
$('.image').load(function(){
// stuff
}).attr('src', 'new_src');
Я на самом деле получил эту идею из комментариев здесь: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-using-jquery/
Я понятия не имею, почему это работает, но я проверил это на IE7 и где он сломался, прежде чем теперь работает.
Надеюсь, поможет,
Принятый ответ фактически объясняет, почему:
Если src уже установлен, то событие запускается в кеше, перед тем как вы получите привязанный обработчик события.
$image.load(function(){ something(); }).attr('src', $image.attr('src'));
для сброса исходного источника.
Используя jQuery для генерации нового изображения с помощью src изображения и назначая непосредственно для него метод загрузки, метод загрузки успешно вызывается, когда jQuery завершает генерацию нового изображения. Это работает для меня в IE 8, 9 и 10
$('<img />', {
"src": $("#img").attr("src")
}).load(function(){
// Do something
});
Решение, которое я нашел, 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;
Модификация примера GUS:
$(document).ready(function() {
var tmpImg = new Image() ;
tmpImg.onload = function() {
// Run onload code.
} ;
tmpImg.src = $('#img').attr('src');
})
Установите источник до и после загрузки.
src
перед тем, как присоединять onload
обработчик, а потом будет достаточно.
Просто добавьте аргумент src в отдельную строку после определения изображения. Это обманом заставит IE запустить лад-событие. Это уродливо, но это самый простой обходной путь, который я нашел до сих пор.
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.target.width будет неопределенным. Событие load сработало бы, но я не смог получить размеры изображения в IE (сработал chrome + FF).
Оказывается, вам нужно искать e.currentTarget.naturalWidth & e.currentTarget.naturalHeight .
Еще раз, IE делает вещи своим собственным (более сложным) способом.
Вы можете решить вашу проблему, используя плагин JAIL, который также позволяет лениво загружать изображения (улучшая производительность страницы) и передавая обратный вызов в качестве параметра
$('img').asynchImageLoader({callback : function(){...}});
HTML должен выглядеть так
<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
Если вам нужно чистое решение CSS, этот прием работает очень хорошо - используйте объект transform. Это также работает с изображениями, когда они кэшированы или нет:
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