HTML5 Canvas toDataURL返回"数据:,"在Firefox

时间:2016-12-01 10:53:13

标签: javascript canvas todataurl

我希望用户按此顺序执行操作:

  • 使用文件输入选择照片。
  • 查看图像正在压缩的通知。
  • 请参阅灰色div中的压缩照片。

问题是什么:

所选的照片不会显示,div仍为灰色。这只发生在Firefox(50.0.2)中,但并非总是如此。看起来像照片(例如18 MB)越大,我在压缩过程中移动鼠标的次数越多,它就越有可能发生。 (不确定,直到测试。)



document.addEventListener('change', function(event) {
  if (event.target.files && event.target.files[0]) {
    toast('One moment please, the photo is being compressed...', true);

    var reader = new FileReader();

    reader.onload = function(event) {
      var r = event.target.result;

      setTimeout(function() {
        compress(r, function(compressed) {
          document.querySelector('#image').style.backgroundImage = 'url(' + compressed + ')';
          clearToast();
        });
      }, 10);
    }

    reader.readAsDataURL(event.target.files[0]);
  }
});

function compress(source_img_obj, callback, maxWidth, quality, output_format) {
  var tmp = new Image();
  tmp.src = source_img_obj;

  var source_img_obj = tmp;
  var maxWidth = maxWidth || 1123;
  var mime_type = (typeof output_format !== 'undefined' && output_format == 'png') ? 'image/png' : 'image/jpeg';
  var natW = source_img_obj.naturalWidth;
  var natH = source_img_obj.naturalHeight;
  var quality = quality || 60;
  var ratio = natH / natW;

  if (natW > maxWidth) {
    natW = maxWidth;
    natH = ratio * maxWidth;
  }

  var cvs = document.createElement('canvas');
  cvs.width = natW;
  cvs.height = natH;

  var ctx = cvs.getContext('2d').drawImage(source_img_obj, 0, 0, natW, natH);
  var result = cvs.toDataURL(mime_type, quality / 100);

  if (typeof callback == 'function') callback(result);

  return result;
};

function toast(txt, sticky) {
  window.toastSticky = (typeof sticky != 'boolean' ? false : sticky);
  var t = document.querySelector('header p');
  if (!t.classList.contains('toast')) {
    window.toastOriginalText = t.innerHTML;
    t.innerHTML = '';
    t.classList.add('toast');
  }
  t.innerHTML = txt;
  if (typeof sticky === 'undefined' || !sticky) {
    window.toastTimeouts = (window.toastTimeouts || 0) + 1;
    setTimeout(function() {
      clearToast(true);
    }, 2000);
  }
};

function clearToast(isTimeout) {
  var isTimeout = (typeof isTimeout != 'boolean' ? false : isTimeout);
  if (isTimeout) window.toastTimeouts--;
  var t = document.querySelector('header p');
  if (t.classList.contains('toast') && !(isTimeout && (window.toastTimeouts > 0 || window.toastSticky))) {
    t.innerHTML = '';
    t.classList.remove('toast');
    t.innerHTML = window.toastOriginalText;
  }
};

#image {
  background: grey;
  background-size: cover;
  height: 200px;
  margin: 10px;
  width: 200px;
}

<header>
  <p>Please upload an image.</p>
</header>
<input type="file" accept="image/*">
<div id="image"></div>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:0)

在压缩之前,您应等待照片加载

document.addEventListener('change', function(event) {
  if (event.target.files && event.target.files[0]) {
    toast('One moment please, the photo is being compressed...', true);

    var reader = new FileReader();

    reader.onload = function(event) {
      var r = event.target.result;

      setTimeout(function() {
        compress(r, function(compressed) {
          document.querySelector('#image').style.backgroundImage = 'url(' + compressed + ')';
          clearToast();
        });
      }, 10);
    }

    reader.readAsDataURL(event.target.files[0]);
  }
});

function compress(source_img_obj, callback, maxWidth, quality, output_format) {
  var tmp = new Image();

  tmp.onload = function() {
    var source_img_obj = tmp;
    var maxWidth = maxWidth || 1123;
    var mime_type = (typeof output_format !== 'undefined' && output_format == 'png') ? 'image/png' : 'image/jpeg';
    var natW = source_img_obj.naturalWidth;
    var natH = source_img_obj.naturalHeight;
    var quality = quality || 60;
    var ratio = natH / natW;

    if (natW > maxWidth) {
      natW = maxWidth;
      natH = ratio * maxWidth;
    }

    var cvs = document.createElement('canvas');
    cvs.width = natW;
    cvs.height = natH;

    var ctx = cvs.getContext('2d').drawImage(source_img_obj, 0, 0, natW, natH);
    var result = cvs.toDataURL(mime_type, quality / 100);

    if (typeof callback == 'function') callback(result);
  }

  tmp.src = source_img_obj;
};

function toast(txt, sticky) {
  window.toastSticky = (typeof sticky != 'boolean' ? false : sticky);
  var t = document.querySelector('header p');
  if (!t.classList.contains('toast')) {
    window.toastOriginalText = t.innerHTML;
    t.innerHTML = '';
    t.classList.add('toast');
  }
  t.innerHTML = txt;
  if (typeof sticky === 'undefined' || !sticky) {
    window.toastTimeouts = (window.toastTimeouts || 0) + 1;
    setTimeout(function() {
      clearToast(true);
    }, 2000);
  }
};

function clearToast(isTimeout) {
  var isTimeout = (typeof isTimeout != 'boolean' ? false : isTimeout);
  if (isTimeout) window.toastTimeouts--;
  var t = document.querySelector('header p');
  if (t.classList.contains('toast') && !(isTimeout && (window.toastTimeouts > 0 || window.toastSticky))) {
    t.innerHTML = '';
    t.classList.remove('toast');
    t.innerHTML = window.toastOriginalText;
  }
};
#image {
  background: grey;
  background-size: cover;
  height: 200px;
  margin: 10px;
  width: 200px;
}
<header>
  <p>Please upload an image.</p>
</header>
<input type="file" accept="image/*">
<div id="image"></div>