Я хочу зробити:
$("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 там, де він не потрібен :) Але створення іншого зображення здається надмірним в будь-якому випадку ІМО.
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/isissue/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 в окремий рядок після того, як буде визначено oject oject. Це наштовхне 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 під реальну картину.
У мене була ця проблема з IE, де e.target.width було б не визначено. Подія завантаження запуститься, але я не зміг отримати розміри зображення в 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 рішення, цей трюк працює дуже добре - використовуйте об'єкт перетворення. Це також працює із зображеннями, коли вони кешовані чи ні:
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