Sto utilizzando FileReader per visualizzare immagini locali in un'applicazione Backbone. Le immagini più piccole vengono visualizzate immediatamente senza problemi, ma quando le immagini sono di diversi megabyte o più grandi, occorrono Chrome 2 o 3 secondi per caricare l'immagine (su un nuovo MacBook Pro con 8 GB di RAM).Problemi di prestazioni durante il caricamento di immagini locali nel browser
Come indicato nei commenti, le immagini di grandi dimensioni vengono caricate istantaneamente in this File API tutorial, quindi il problema non è con FileReader
ma con la mia particolare implementazione in Backbone.
Ho incluso il modello Backbone pertinente e la vista qui sotto. Ecco una descrizione dei logica:
- Il modello crea una nuova
FileReader
nella quale viene fatto passare il percorso del file. - Una volta caricato il file, viene creato uno
Image
esrc
diImage
viene impostato sull'URL dati fornito daFileReader
. - Una volta caricata l'immagine, il modello viene aggiornato con la larghezza e l'altezza dell'immagine (utilizzata altrove nell'applicazione) e l'attributo
initialized
del modello è impostato sutrue
(quindi viene generato un eventochange
sul modello). - Quando la vista rileva l'evento
change
sul modello, viene chiamata la funzionerender
, che sostituisce l'immagine di sfondo didiv
con l'URL di dati.
Backbone Modello
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 Vedi
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") + ")"});
},
});
Di seguito uno screenshot della timeline Chrome. Il ritardo più grande sembra verificarsi tra la richiesta dell'URL di dati e l'evento di caricamento (che rappresenta circa 0,5 secondi). Non sono sicuro di cosa sia "Ricalcola stile". Non sono nemmeno sicuro del motivo per cui ci sono così tanti eventi di disegno (sembra che si tratti di rendering nell'area della barra di scorrimento).
SOLUZIONE
ho dato per scontato che il browser sarà in grado di ridimensionare le immagini in modo nativo in modo più efficiente rispetto a qualsiasi soluzione di JavaScript, ma questa ipotesi era sbagliato. Ridimensionando le immagini prima di vengono visualizzate, sono stato in grado di ridurre il ritardo a circa 50 millisecondi. Ho utilizzato un plug-in open source chiamato JavaScript Load Image per gestire il caricamento e il ridimensionamento delle immagini (utilizza il tag HTML5 canvas
). Ecco il mio modello di dorsale modificato:
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});
},
});
Questo era esattamente il problema. Avevo pensato che il browser sarebbe stato più efficiente nel ridimensionare l'immagine in modo nativo piuttosto che richiamare una soluzione JavaScript. Tuttavia, questo non è il caso. Ridimensionando l'immagine prima che venga visualizzata, ho completamente eliminato il ritardo. Il plugin che hai suggerito è assolutamente perfetto per questo scenario. Grazie! –
Sono contento che abbia funzionato per voi, complimenti a https://github.com/blueimp per il duro lavoro! – lazd