2013-07-03 13 views
18

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:

  1. Il modello crea una nuova FileReader nella quale viene fatto passare il percorso del file.
  2. Una volta caricato il file, viene creato uno Image e src di Image viene impostato sull'URL dati fornito da FileReader.
  3. 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 su true (quindi viene generato un evento change sul modello).
  4. Quando la vista rileva l'evento change sul modello, viene chiamata la funzione render, che sostituisce l'immagine di sfondo di div 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).

Chrome Timeline

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}); 
    }, 
}); 

risposta

7

Ho riscontrato lo stesso problema durante il caricamento di immagini di grandi dimensioni con FileReader. Se non hai intenzione di visualizzarli a grandezza originale, sembra che la soluzione sia quella di ridimensionare l'immagine prima di visualizzarla utilizzando un elemento canvas.

Dopo il successo misto con la mia implementazione, ho deciso di utilizzare JavaScript Load Image (licenza MIT) e l'opzione maxWidth, che ha risolto questo e altri problemi (imprevisti).

Provate il the demo e vedete se le vostre immagini si caricano bene.

+1

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! –

+0

Sono contento che abbia funzionato per voi, complimenti a https://github.com/blueimp per il duro lavoro! – lazd

Problemi correlati