Tôi muốn làm:
$("img").bind('load', function() {
// do stuff
});
Nhưng sự kiện tải không kích hoạt khi hình ảnh được tải từ bộ đệm. Các tài liệu jQuery đề xuất một plugin để sửa lỗi này, nhưng nó không hoạt động
Tôi muốn làm:
$("img").bind('load', function() {
// do stuff
});
Nhưng sự kiện tải không kích hoạt khi hình ảnh được tải từ bộ đệm. Các tài liệu jQuery đề xuất một plugin để sửa lỗi này, nhưng nó không hoạt động
Câu trả lời:
Nếu src
đã được đặt, thì sự kiện sẽ kích hoạt trong trường hợp được lưu trong bộ nhớ cache, trước khi bạn thậm chí bị ràng buộc trình xử lý sự kiện. Để khắc phục điều này, bạn có thể lặp qua kiểm tra và kích hoạt sự kiện dựa trên .complete
, như thế này:
$("img").one("load", function() {
// do stuff
}).each(function() {
if(this.complete) {
$(this).load(); // For jQuery < 3.0
// $(this).trigger('load'); // For jQuery >= 3.0
}
});
Lưu ý thay đổi từ .bind()
để .one()
xử lý sự kiện không chạy hai lần.
setTimeout(function(){//do stuff},0)
chức năng trong 'tải' ... 0 cung cấp thêm cho hệ thống trình duyệt (DOM) để đảm bảo mọi thứ được cập nhật chính xác.
.load()
không kích hoạt sự kiện và có 1 đối số bắt buộc, .trigger("load")
thay vào đó , hãy sử dụng
Tôi có thể đề nghị bạn tải lại nó vào một đối tượng hình ảnh không phải DOM không? Nếu được lưu trong bộ nhớ cache, việc này sẽ không mất thời gian và tải sẽ vẫn kích hoạt. Nếu nó không được lưu trong bộ nhớ cache, nó sẽ kích hoạt tải khi hình ảnh được tải, cùng lúc với phiên bản DOM của hình ảnh kết thúc tải.
Javascript:
$(document).ready(function() {
var tmpImg = new Image() ;
tmpImg.src = $('#img').attr('src') ;
tmpImg.onload = function() {
// Run onload code.
} ;
}) ;
Đã cập nhật (để xử lý nhiều hình ảnh và với tệp đính kèm tải được sắp xếp chính xác):
$(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
trình xử lý trước khi nó được thêm vào, điều này cũng không hoạt động nhưng đối với một hình ảnh, mã OP hoạt động với nhiều người :)
#img
là một ID không phải là một bộ chọn phần tử :) Cũng this.src
hoạt động, không cần sử dụng jQuery khi không cần thiết :) Nhưng việc tạo một hình ảnh khác có vẻ như quá mức cần thiết trong cả hai trường hợp IMO.
imageLoaded
đó, hãy sử dụngtmp.onload = imageLoaded.bind(this)
Giải pháp đơn giản của tôi, nó không cần bất kỳ plugin bên ngoài nào và đối với các trường hợp phổ biến là đủ:
/**
* 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);
});
}
});
};
sử dụng nó như thế này:
onImgLoad('img', function(){
// do stuff
});
ví dụ, để làm mờ dần hình ảnh của bạn khi tải, bạn có thể làm:
$('img').hide();
onImgLoad('img', function(){
$(this).fadeIn(700);
});
Hoặc thay thế, nếu bạn thích một cách tiếp cận giống như plugin 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);
và sử dụng nó theo cách này:
$('img').imgLoad(function(){
// do stuff
});
ví dụ:
$('img').hide().imgLoad(function(){
$(this).fadeIn(700);
});
width
, max-height
và nghỉ height:auto
, thường đó là cần thiết để thiết lập cả chiều rộng và chiều cao chỉ khi bạn cần phải căng hình ảnh; để có giải pháp mạnh mẽ hơn, tôi sẽ sử dụng một plugin như ImagesLoaded
Bạn có thực sự phải làm điều đó với jQuery không? Bạn cũng có thể đính kèm onload
sự kiện trực tiếp vào hình ảnh của mình;
<img src="/path/to/image.jpg" onload="doStuff(this);" />
Nó sẽ kích hoạt mỗi khi hình ảnh được tải, từ bộ đệm hay không.
onload
trình xử lý sẽ kích hoạt khi hình ảnh được tải lần thứ hai từ bộ đệm?
Bạn cũng có thể sử dụng mã này với sự hỗ trợ cho lỗi tải:
$("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
trình xử lý trước và sau đó gọi nó sau trong each
chức năng.
Tôi chỉ gặp vấn đề này một mình, tìm kiếm mọi giải pháp không liên quan đến việc giết bộ nhớ cache hoặc tải xuống plugin.
Tôi đã không thấy chủ đề này ngay lập tức vì vậy tôi đã tìm thấy một cái gì đó khác thay vào đó là một sửa chữa thú vị và (tôi nghĩ) xứng đáng để đăng ở đây:
$('.image').load(function(){
// stuff
}).attr('src', 'new_src');
Tôi thực sự có ý tưởng này từ các ý kiến ở đây: http://www.witheringtree.com/2009/05/image-load-event-binding-with-ie-USE-jquery/
Tôi không biết tại sao nó hoạt động nhưng tôi đã thử nghiệm điều này trên IE7 và nó đã bị hỏng trước khi nó hoạt động.
Hy vọng nó giúp,
Câu trả lời được chấp nhận thực sự giải thích tại sao:
Nếu src đã được đặt thì sự kiện sẽ kích hoạt trong bộ đệm được đặt trước khi bạn xử lý ràng buộc sự kiện.
$image.load(function(){ something(); }).attr('src', $image.attr('src'));
để thiết lập lại nguồn ban đầu.
Bằng cách sử dụng jQuery để tạo một hình ảnh mới với src của hình ảnh và gán phương thức tải trực tiếp vào đó, phương thức tải được gọi thành công khi jQuery hoàn thành việc tạo hình ảnh mới. Điều này làm việc cho tôi trong IE 8, 9 và 10
$('<img />', {
"src": $("#img").attr("src")
}).load(function(){
// Do something
});
Một giải pháp tôi tìm thấy https://bugs.chromium.org/p/chromium/issues/detail?id=7731#c12 (Mã này được lấy trực tiếp từ nhận xét)
var photo = document.getElementById('image_id');
var img = new Image();
img.addEventListener('load', myFunction, false);
img.src = 'http://newimgsource.jpg';
photo.src = img.src;
Một sửa đổi cho ví dụ của GUS:
$(document).ready(function() {
var tmpImg = new Image() ;
tmpImg.onload = function() {
// Run onload code.
} ;
tmpImg.src = $('#img').attr('src');
})
Đặt nguồn trước và sau khi tải.
src
trước khi đính kèm onload
trình xử lý, một lần sau đó sẽ đủ.
Chỉ cần thêm lại đối số src trên một dòng riêng sau khi xác định oject img. Điều này sẽ lừa IE kích hoạt sự kiện lad. Nó là xấu, nhưng đó là cách giải quyết đơn giản nhất mà tôi tìm thấy cho đến nay.
jQuery('<img/>', {
src: url,
id: 'whatever'
})
.load(function() {
})
.appendTo('#someelement');
$('#whatever').attr('src', url); // trigger .load on IE
Tôi có thể cho bạn một lời khuyên nhỏ nếu bạn muốn làm như thế này:
<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>
Nếu bạn làm điều đó khi trình duyệt lưu trữ hình ảnh, không có vấn đề gì luôn luôn hiển thị img nhưng tải img dưới hình ảnh thực.
Tôi đã gặp vấn đề này với IE trong đó e.target. Thong sẽ không được xác định. Sự kiện tải sẽ kích hoạt nhưng tôi không thể lấy kích thước của hình ảnh trong IE (chrome + FF hoạt động).
Hóa ra bạn cần tìm e.cienTarget.naturalWidth & e.cienTarget.naturalHeight .
Một lần nữa, IE thực hiện mọi thứ theo cách riêng (phức tạp hơn).
Bạn có thể giải quyết vấn đề của mình bằng cách sử dụng plugin JAIL cũng cho phép bạn lười tải hình ảnh (cải thiện hiệu suất trang) và chuyển cuộc gọi lại dưới dạng tham số
$('img').asynchImageLoader({callback : function(){...}});
HTML sẽ giống như
<img name="/global/images/sample1.jpg" src="/global/images/blank.gif" width="width" height="height" />
Nếu bạn muốn một giải pháp CSS thuần túy, thủ thuật này hoạt động rất tốt - sử dụng đối tượng biến đổi. Điều này cũng hoạt động với hình ảnh khi chúng được lưu trữ hay không:
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