2016-03-25 4 views
0

Рассмотрите этот JSFiddle. В нем я выбираю фотографии, которые я тогда хочу кодировать base64, используя canvas, чтобы я мог хранить их в sessionStorage для отложенной загрузки. Поскольку я устанавливаю его для нескольких файлов, я прохожу через каждый из них и создаю изображение и холст, но независимо от того, что он просто выводит точно такое же кодированное изображение base64 каждый раз. Благодаря тестированию я знаю, что на каждой итерации цикла изображение отличается и действительно указывает на другой файл blob, но холст просто выводит одно и то же снова и снова, что, я думаю, также является последним файлом в списке файлов. Иногда он также выводит строку «data», и это все. Мне бы это понравилось, если кто-то может указать мне в правильном направлении.HTML5 Canvas toDataURL всегда то же самое в цикле for

Кодекс шоу ниже:

HTML

<style type="text/css"> 
    input[type="file"] { 
     display: none; 
    } 

    a { 
     display: inline-block; 
     margin: 6px; 
    } 
</style> 
<form action="#" method="post"> 
    <input type="file" accept="image/*" multiple /> 
    <button type="button">Select Photos</button> 
</form> 
<nav></nav> 

JavaScript

console.clear(); 
 

 
$(function() { 
 
    $("button[type=button]").on("click", function (e) { 
 
    $("input[type=file]").trigger("click"); 
 
    }); 
 
    
 
    $("input[type=file]").on("change", function (e) { 
 
    var nav = $("nav").empty(); 
 
    
 
    for (var i = 0, l = this.files.length; i < l; i++) { 
 
     var file = this.files[i], 
 
      image = new Image(); 
 
      
 
     $(image).on("load", i, function (e) { 
 
     var canvas = document.createElement("canvas"), 
 
      context = canvas.getContext("2d"); 
 
     
 
     \t canvas.height = this.height; 
 
     \t canvas.width = this.width; 
 
     \t 
 
     context.drawImage(this, 0, 0); 
 
     
 
     nav.append("<a href=\"" + canvas.toDataURL("image/jpeg") + "\" target=\"_blank\">" + e.data + "</a>"); 
 
     
 
     URL.revokeObjectURL(this.src); 
 
     }); 
 
     
 
     image.src = URL.createObjectURL(file); 
 
    } 
 
    }); 
 
});

+3

Это потому, что ваш '.он («нагрузка»)' обработчик асинхронный – adeneo

+0

Я не уверен, что вы просите. Кажется, он работает правильно на моей стороне. – Chris

+0

Когда я показываю холст, он отображает каждое изображение, а встроенные источники изображения также правильны, вам нужно будет уточнить, чего вы хотите, иначе я не смогу вам помочь. – Chris

ответ

2

, но независимо от того, что это только кажется, что выход на точно такое же base64 кодированное изображение каждый раз.

.load() событие асинхронное. Вы можете использовать $.when(), $.Deferred(), заменить $.map() на for цикл для обработки асинхронно загружен img элементов. Предостережение о том, что отображаемый текст элемента a не может быть в цифровом порядке; который можно отрегулировать путем сортировки элементов по адресу .then(); хотя и не рассматриваются в вопросе, если это необходимо, также может быть достигнуто перечисление или загрузка изображений.

$("input[type=file]").on("change", function(e) { 
    var nav = $("nav").empty(); 
    var file = this.files 
    $.when.apply($, $.map(file, function(img, i) {  
     return new $.Deferred(function(dfd) { 
     var image = new Image(); 
     $(image).on("load", i, function(e) { 
      var canvas = document.createElement("canvas") 
      , context = canvas.getContext("2d"); 
      canvas.height = this.height; 
      canvas.width = this.width;  
      context.drawImage(this, 0, 0);  
      nav.append("<a href=\"" 
        + canvas.toDataURL() 
        + "\" target=\"_blank\">" 
        + e.data + "</a>"); 
      dfd.resolve() 
      URL.revokeObjectURL(this.src); 
     }); 
     image.src = URL.createObjectURL(img); 
     return dfd.promise() 
     }) 
    })).then(function() { 
     nav.find("a").each(function() { 
     console.log(this.href + "\n"); 
     }) 
    }) 
    }); 
}) 

jsfiddle https://jsfiddle.net/bc6x3s02/19/

+0

У меня все в порядке с асинхронными и неуправляемыми оговорками. В конечном итоге я буду хранить изображения в 'sessionStorage', где фоновый загрузчик подберет их и продолжит, поэтому я не буду отображать какие-либо визуальные запросы за пределами« остающегося x-образа ». – Gup3rSuR4c

+0

* «Если в загруженном изображении нет установленного параметра« image/jpeg », изображение может не отображаться правильно» «Подождите, что!» Изображения, сделанные на холсте, являются декодированными изображениями, независимо от того, были ли они кадром jpeg gif png или другим холстом, как только на холсте это всего лишь набор необработанных пикселей.Вторая часть этого предложения действительно почти правильна, за исключением того, что ** будет ** неточным отражением правильного URI данных файла изображения из-за процесса декодирования-перекодирования. Если OP хотел dataURI файла без перекодирования в jpeg, он должен был использовать 'FileReader'. – Kaiido

+0

@Kaiido Что вы рассматриваете как «не-смысл»? Является ли этот термин обязательным для сообщения о точках, которые вы делаете? Пробовал исходную версию jsfiddle с разными изображениями. Изображения не отображались корректно до тех пор, пока не исчезнет «image/jpeg» '. Не стесняйтесь редактировать ответ или передайте то, что, по вашему мнению, должно быть правильным объяснением для улучшения ответа. – guest271314

Смежные вопросы