2013-05-07 14 views
9

jsFiddle URL: http://jsfiddle.net/Xotic750/AjtLxKorzystanie readAsDataURL() do podglądu obrazu

pracuje nad tym cały dzień i nie widzę problemu. Prawdopodobnie wynika to z mojego wąskiego rozumienia sposobu działania obiektów FileReader, ale próbuję użyć funkcji readAsDataURL() w celu uzyskania obrazów wybranych przez użytkownika i wyświetlenia ich podglądu na ekranie w tabeli. Wszystko działa bez ... zgadłeś ... podgląd ... dobrze. Myślę, że jestem blisko, ponieważ podgląd zadziała, ALE wyświetli tylko ostatni obraz z zestawu. Powiedzmy na przykład, że gdybym załadował 6 obrazów, wtedy pierwszy rząd 3 obrazów zostałby złamany, w drugim rzędzie pierwsze 2 byłyby zerwane, a ostateczne szóste zdjęcie wyświetliło podgląd .... Każda rada bardzo się spodobała. Ponadto, raz to działa może pomóc inni próbują zrobić to samo, bo Rozglądałem całego rozwiązania tego problemu, a ja nie potrafię kopać nic się ....

function PreviewImages() { 
    var inputID = document.getElementById('input_clone'); 
    var totalImages = inputID.files.length; 
    var imagesPerRow = 3; 
    var numRows = totalImages/imagesPerRow; 
    var row = ""; 
    var cell = ""; 
    var element1 = ""; 
    var elementID = ""; 


    for(var i = 0; i < numRows; i++){ //create rows 
     row = document.getElementById('image_preview_table').insertRow(i); 
     for(var ii = 0; ii < imagesPerRow; ii++){ //create cells 
      cell = row.insertCell(ii); 
      elementID = "img_" + ii; 
      element1 = document.createElement("img"); 
      element1.name = elementID; 
      element1.id = elementID 
      cell.appendChild(element1); 

      oFReader = new FileReader(); 

      oFReader.onload = function(oFREvent){ 
       var dataURI = oFREvent.target.result; 
       var image = document.getElementById(elementID); 
       image.src = dataURI; 
      }; 

       oFReader.readAsDataURL(document.getElementById("input_clone").files[ii]); 

    } 
} 
} 

Odpowiedz

10

Tutaj jest rozwiązaniem, wprowadzono sporo korekty do oryginału, aby to zadziałało, jak zapewne zauważysz.

CSS

div.rounded { 
    width: 100%; 
    border-style: solid; 
    border-width: 1px; 
    border-radius: 5px; 
} 
label { 
    display: block; 
} 
input { 
    display: block; 
} 
#previewTable { 
    width: 100%; 
} 

HTML

<div id="imagesDiv" class="rounded"> 
    <label for="chooseFiles">Add Images</label> 
    <input type="file" id="chooseFiles" multiple="multiple" /> 
    <table id="previewTable"> 
     <thead id="columns"></thead> 
     <tbody id="previews"></tbody> 
    </table> 
</div> 

JavaScript

(function (global) { 
    var imagesPerRow = 3, 
     chooseFiles, 
     columns, 
     previews; 

    function PreviewImages() { 
     var row; 

     Array.prototype.forEach.call(chooseFiles.files, function (file, index) { 
      var cindex = index % imagesPerRow, 
       oFReader = new FileReader(), 
       cell, 
       image; 

      if (cindex === 0) { 
       row = previews.insertRow(Math.ceil(index/imagesPerRow)); 
      } 

      image = document.createElement("img"); 
      image.id = "img_" + index; 
      image.style.width = "100%"; 
      image.style.height = "auto"; 
      cell = row.insertCell(cindex); 
      cell.appendChild(image); 

      oFReader.addEventListener("load", function assignImageSrc(evt) { 
       image.src = evt.target.result; 
       this.removeEventListener("load", assignImageSrc); 
      }, false); 

      oFReader.readAsDataURL(file); 
     }); 
    } 

    global.addEventListener("load", function windowLoadHandler() { 
     global.removeEventListener("load", windowLoadHandler); 
     chooseFiles = document.getElementById("chooseFiles"); 
     columns = document.getElementById("columns"); 
     previews = document.getElementById("previews"); 

     var row = columns.insertRow(-1), 
      header, 
      i; 

     for (i = 0; i < imagesPerRow; i += 1) { 
      header = row.insertCell(-1); 
      header.style.width = (100/imagesPerRow) + "%"; 
     } 

     chooseFiles.addEventListener("change", PreviewImages, false); 
    }, false); 
}(window)); 

Na jsfiddle

+0

Nice! Wydaje się działać świetnie w chrome, ale problem w firefox. – commanderZiltoid

+1

Sam przyjrzałem się i znalazłem problem. Drugi parametr faktycznie nie jest opcjonalny w 'removeEventListener'. Wygląda na to, że Chrome nie narzeka, ale Firefox to robi. Zmodyfikowane skrzypce można znaleźć na http://jsfiddle.net/6cgTj/23/. –

+1

@Ray Nicholas, tak, to jest problem w Firefoksie. Zaktualizowałem i wszystkie powinny działać. – Xotic750

10

Problem z kodem jest: readAsDataURL() jest asynchroniczna, powinieneś poczekać, aż zakończy czytanie, zanim wywołasz drugie czytanie lub zrobisz nowe wystąpienie, wywołując nowy FileReader().

Odpowiedź Xotic750 działa, ponieważ tworzy jeden FileReader dla każdego obrazu, podczas gdy używałeś tylko jednego FileReadera.

Jednak użycie FileReadera do podglądu obrazów nie jest dobrym wyborem, ponieważ FileReader.readAsDataURL() konwertuje cały obraz na duży ciąg znaków (w postaci "data: image/jpeg; base64,/9j/4SVaRXhpZgAAS. ..... "), a pokazujesz obraz, umieszczając cały ciąg danych obrazu w atrybucie img.src, jeśli twój obraz jest duży, ryzykujesz wyczerpaniem pamięci.

img.src jest przeznaczony do przechowywania adresu URL obrazu, a nie danych obrazu, chociaż można przypisać adres URL zawierający dane całego obrazu poprzez img.src = "data: image/jpeg; ... ... ".

Tak, należy użyć window.URL.createObjectURL(), aby utworzyć link odsyłający do lokalnego obrazu i przypisać ten adres URL do img.src:

... 
img.src = window.URL.createObjectURL(fileInput.files[i]); 
... 
+0

Dziękuję za skierowanie dataUrl i , zmagałem się z blokowaniem podglądu interfejsu użytkownika przy ładowaniu umiarkowanie dużych obrazów (> 200kb) –