Tôi đang sử dụng FileReader để hiển thị hình ảnh cục bộ trong ứng dụng Backbone. Các hình ảnh nhỏ hơn được hiển thị ngay lập tức mà không gặp bất kỳ sự cố nào, nhưng khi hình ảnh có kích thước từ vài megabyte trở lên, phải mất Chrome 2 hoặc 3 giây để tải hình ảnh (trên MacBook Pro hoàn toàn mới với RAM 8 GB).Sự cố hiệu suất khi tải hình ảnh cục bộ vào trình duyệt
Như đã nêu trong các nhận xét, hình ảnh lớn tải ngay lập tức trong this File API tutorial, vì vậy vấn đề không phải là với FileReader
mà đúng hơn là với việc triển khai cụ thể của tôi trong Backbone.
Tôi đã bao gồm mô hình Backbone có liên quan và xem bên dưới. Dưới đây là phác thảo của logic:
- Mô hình tạo một đường dẫn tệp mới được chuyển.
- Khi tệp được tải,
Image
được tạo vàsrc
củaImage
được đặt thành URL dữ liệu được cung cấp bởiFileReader
. - Khi hình ảnh đã được tải, mô hình được cập nhật với chiều rộng và chiều cao của hình ảnh (được sử dụng ở nơi khác trong ứng dụng) và thuộc tính
initialized
của mô hình được đặt thànhtrue
(do đó kích hoạt sự kiệnchange
trên mô hình). - Khi chế độ xem phát hiện sự kiện
change
trên mô hình, hàmrender
được gọi, thay thế hình nền củadiv
bằng URL dữ liệu.
Backbone Mẫu
var PhotoModel = Backbone.Model.extend({
initialize: function() {
this.set({"available": true});
this.initialized = false;
if (this.get("file")) {
this.uploadPhoto();
}
},
uploadPhoto: function() {
var file = this.get("file");
var reader = new FileReader();
var model = this;
reader.onload = function(event) {
var image = new Image();
image.onload = function() {
model.set({width: this.width, height: this.height});
model.set("initialized", true);
};
image.src = event.target.result;
model.set("dataURL", event.target.result);
}
reader.readAsDataURL(file);
},
});
Backbone Xem
var PhotoFormView = Backbone.View.extend({
className: "photo-form",
initialize: function() {
this.listenTo(this.model, "change", this.render);
this.render();
},
render: function() {
$(this.el).find(".photo").css({"background-image": "url(" + this.model.get("dataURL") + ")"});
},
});
Dưới đây là một ảnh chụp màn hình của timeline Chrome. Sự chậm trễ lớn nhất dường như xảy ra giữa yêu cầu URL dữ liệu và sự kiện tải (điều này chiếm khoảng 0,5 giây). Tôi không chắc chắn những gì "tính toán lại phong cách" là tất cả về. Tôi cũng không chắc chắn tại sao có rất nhiều sự kiện sơn (nó xuất hiện để được dựng hình trong khu vực thanh cuộn).
SOLUTION
tôi đã giả định rằng trình duyệt sẽ có thể tự nhiên thay đổi kích thước hình ảnh một cách hiệu quả hơn bất kỳ giải pháp JavaScript, nhưng giả định này là sai. Bằng cách đổi kích thước hình ảnh trước khi chúng được hiển thị, tôi có thể giảm độ trễ xuống khoảng 50 mili giây. Tôi đã sử dụng plugin nguồn mở có tên là JavaScript Load Image để xử lý việc tải và thay đổi kích thước hình ảnh (nó sử dụng thẻ HTML5 canvas
). Đây là mô hình Backbone đã sửa đổi của tôi:
var PhotoModel = Backbone.Model.extend({
initialize: function() {
this.set({available: true});
this.set({initialized: false});
if (this.get("file")) {
this.uploadPhoto();
}
},
uploadPhoto: function() {
var model = this;
loadImage(this.get("file"), function (img) {
model.set({img: img});
model.set({initialized: true});
}, {maxHeight: 344});
},
});
Đây chính xác là vấn đề. Tôi đã giả định rằng trình duyệt sẽ hiệu quả hơn trong việc thay đổi kích thước hình ảnh một cách nguyên bản hơn là gọi một giải pháp JavaScript. Tuy nhiên, đây không phải là trường hợp. Bằng cách thay đổi kích thước hình ảnh trước khi nó được hiển thị, tôi đã loại bỏ hoàn toàn độ trễ. Plugin bạn đề xuất là hoàn toàn hoàn hảo cho trường hợp này. Cảm ơn! –
Tôi rất vui vì đã làm việc cho bạn, kudo đến https://github.com/blueimp vì công việc khó khăn! – lazd