1

这是我的每个循环:-

var image_obj = {};

$(".wrapper").each(function (index, data) {
  var dfile = this.getElementsByClassName('image')[0];
  file = dfile.files[0];
  if(file != null) {
    var fr = new FileReader();


fr.onload = function (e) {

          img = new Image();
          img.onload = function (k) {
            var canvas = document.createElement("canvas");
            canvas.width = img.width;
            canvas.height = img.height;
            var ctx = canvas.getContext("2d");
            ctx.drawImage(img, 0, 0);
            objindex = "obj_" + index;
            image_obj[objindex] = canvas.toDataURL("image/jpeg");

          };
          img.src = fr.result;
        };
        fr.readAsDataURL(file);
      }
    });

我需要每个循环的索引来将 base_64 编码图像保存到对象中。

但是索引没有按顺序显示,因为每个循环执行在到达之前完成canvas.getContext("2d");

4

1 回答 1

0

一个大问题是您需要img在外部函数内部声明:

$(".wrapper").each(function (index, data) {
  var img;

原因是,否则,img是一个全局的。img在您的函数中捕获的变量onload只包含该全局的当前值,这就是分配给它的最新each调用(可能是 jquery 对象中的最后一个包装器)。然后当onload被调用时,它将错误的图像写入画布。通过声明变量,您可以确保每个外部函数范围都有自己的img变量供您的onload函数捕获,然后它们将在实际应用时使用这些变量。

编辑如果你想确保输出的顺序是正确的,你应该在最后整理出来,因为你不控制什么时候onload运行;这就是它的美妙之处。我会做这样的事情:

ctx.drawImage(img, 0, 0);
if (typeof(image_obj.images) == "undefined")
  image_obj.images = [];
image_obj.images[index] = canvas.toDataURL("image/jpeg");

或者只是让image_obj自己成为一个数组,然后做:

ctx.drawImage(img, 0, 0);
image_arr[index] = canvas.toDataURL("image/jpeg");

取决于您是否需要将该对象作为其他东西的容器。

由于这是一个数组,而不是一个对象,因此图像将是有序的。

编辑 2

所以现在的问题是,如果某些文件不存在,您的阵列中就会出现漏洞。让我们不要发生这种情况:

var index = -1;
$(".wrapper").each(function (_, data) {
  ...
  if(file != null) {
    var fr = new FileReader();
    index++;
    var localIndex = index; //to capture locally

    fr.onload = function (e) {
      ...
      ctx.drawImage(img, 0, 0);
      image_arr[localIndex] = canvas.toDataURL("image/jpeg");
      ..
于 2013-05-01T07:21:11.903 回答