简体   繁体   English

HTML5 Canvas toDataURL在for循环中始终相同

[英]HTML5 Canvas toDataURL is always the same in a for loop

Consider this JSFiddle . 考虑一下这个JSFiddle In it I select photos which I then want to base64 encode using canvas so I can store them in sessionStorage for deferred uploading. 在其中,我选择了一些照片,然后希望使用画布对其进行base64编码,以便将它们存储在sessionStorage以进行延迟上传。 Because I have it set for multiple files, I loop through each one and create an image and a canvas, but no matter what it just seems to output the exact same base64 encoded image every time. 因为我为多个文件设置了该文件,所以我遍历每个文件并创建一个图像和一个画布,但是无论它看起来每次输出完全相同的base64编码图像都是如此。 Through testing I know that on each loop iteration the image is different and does indeed point to a different file blob, but the canvas is just outputting the same thing over and over, which I think is also the last file in the files list. 通过测试,我知道在每次循环迭代中,映像都是不同的,的确指向了不同的文件blob,但是画布只是一遍又一遍地输出相同的内容,我认为这也是文件列表中的最后一个文件。 Sometimes it will also just output a "data," string and that's it. 有时它也只会输出一个“数据”字符串,仅此而已。 I'd love it if someone can point me in the right direction. 如果有人能指出我正确的方向,我会喜欢的。

Code is show below: 代码如下所示:

HTML 的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 的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"); canvas.height = this.height; canvas.width = this.width; 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); } }); }); 

but no matter what it just seems to output the exact same base64 encoded image every time. 但是无论每次看起来都输出完全相同的base64编码图像都是如此。

.load() event is asynchronous. .load()事件是异步的。 You can use $.when() , $.Deferred() , substitute $.map() for for loop to handle asynchronously loaded img elements. 您可以使用$.when() $.Deferred() $.when()$.Deferred()$.map()代替for循环来处理异步加载的img元素。 The caveat that the displayed a element text may not be in numerical order; 注意,显示a元素文本可能不是数字顺序的; which can be adjusted by sorting the elements at .then() ; 可以通过对.then()的元素进行排序来调整; though not addressed at Question, if required, the listing or loading of images sequentially can also be achieved. 尽管没有在Question上解决,但如果需要,也可以按顺序列出或加载图像。

$("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/ jsfiddle https://jsfiddle.net/bc6x3s02/19/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM