【问题标题】:Convert piece of canvas to blob type将一块画布转换为 blob 类型
【发布时间】:2015-12-14 21:13:07
【问题描述】:

我正在尝试优化一些使用 canvas.drawImage() 调用的代码。 当调用数百或数千次时,这是一个相当昂贵的调用。 发现了 canvas.toBlob(callback) 方法,但我想知道是否有办法只获取画布的一部分。

drawimage() 可以更精细地控制应该绘制哪些部分。

canvas.drawImage(canvas, sx, sy, sw, sh, dx, dy, dw, dh);

欢迎任何建议/想法!

【问题讨论】:

    标签: javascript html canvas drawing jpeg


    【解决方案1】:

    canvas.toBlob方法目前只支持火狐浏览器。
    要使其在其他浏览器上运行,您可以使用 this code 将 base64 dataURI 转换为 blob 对象。

    现在,要通过这些方法仅获取画布的一部分,您必须创建一个新画布,将其尺寸设置为裁剪后的尺寸并在其上绘制您想要的部分:

    var img = new Image();
    img.crossOrigin = 'anonymous';
    img.src = "http://i.imgur.com/fHyEMsl.jpg";
    
    var resultImg = new Image();
    var resultSize = document.createElement('span');
    document.body.appendChild(resultImg);
    document.body.appendChild(resultSize);
    
    var cropped = {x: 0, y: 0, width: 130, height: 130};
    
    var canvas = document.createElement('canvas');
    document.body.appendChild(canvas);
    
    img.onload = function() {
      canvas.width = this.width;
      canvas.height = this.height;
      canvas.getContext('2d').drawImage(this, 0, 0);
      setInterval(cropCanvas, 1000);
    }
    
    function cropCanvas() {
      URL.revokeObjectURL(resultImg.src);
      var newCanvas = document.createElement('canvas');
      newCanvas.width = cropped.width;
      newCanvas.height = cropped.height;
      newCanvas.getContext('2d').drawImage(canvas, -cropped.x, -cropped.y);
      if (newCanvas.toBlob) { // Firefox
        newCanvas.toBlob(function(blob) {
          resultImg.src = URL.createObjectURL(blob);
          resultSize.innerHTML = blob.size + ' bytes';
        }, 'image/jpeg');
      } else { // all other browsers
        var blob = dataURItoBlob(newCanvas.toDataURL('image/jpeg'));
        resultImg.src = URL.createObjectURL(blob);
        resultSize.innerHTML = blob.size + ' bytes';
      }
      //move our crop
      if (cropped.x < img.width - 130)
        cropped.x += 130;
      else {
        if (cropped.y < img.height - 130) {
          cropped.y += 130;
          cropped.x = 0;
        } else {
          cropped.x = 0;
          cropped.y = 0;
        }
      }
    }
    
    // taken from https://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata/5100158#5100158
    function dataURItoBlob(dataURI) {
      var byteString;
      if (dataURI.split(',')[0].indexOf('base64') >= 0)
        byteString = atob(dataURI.split(',')[1]);
      else
        byteString = unescape(dataURI.split(',')[1]);
    
      var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
    
      var ia = new Uint8Array(byteString.length);
      for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
      }
    
      return new Blob([ia], {
        type: mimeString
      });
    }

    【讨论】:

    • 问题是我正在尝试将一块画布转换为 blob 类型,然后再转换为数据 uri。理想情况下,我想完全避免这个画布的 drawimage 方法
    • 如果您不需要 blob,请不要将其转换为 blob,而是直接转换为 dataURL。 toDataURL 方法没有裁剪属性,您必须在另一个画布上绘制它才能进行裁剪。 ps,如果你关心性能,你要知道toDataURLtoBlob类似于5000 times slower than drawimage
    • 嗯,不幸的是。需要找到其他解决方法。
    • 为什么?这就是这样做的方法。只需避免在上面的示例中转换为 blob,您将裁剪 dataURL
    • 但是无论你在做什么,这篇文章都回答了这个问题。这是裁剪 toBlob/toDataURL 的唯一方法。
    猜你喜欢
    • 2015-07-01
    • 2013-05-09
    • 2013-12-15
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 2021-08-04
    • 2018-08-05
    • 2014-07-04
    相关资源
    最近更新 更多