【问题标题】:Crop an image displayed in a Canvas裁剪显示在画布中的图像
【发布时间】:2023-03-09 16:38:01
【问题描述】:

我有一个画布标签:

<canvas width="321" height="240" id="img_source"></canvas>

我想添加裁剪功能,所以我制作了一个可调整大小的 div,它可以通过使用鼠标拖动 div 的角来识别裁剪图像的边框。如下图所示:

我目前正在使用“toDataURL()”将画布中的数据转换为可以通过&lt;img&gt; 标签显示的图像。我的问题是,如何仅将可调整大小的 div 标识的画布的一部分转换为图像?

【问题讨论】:

标签: javascript jquery html css canvas


【解决方案1】:

对选定的矩形坐标使用getImageData 方法。例如:

let imageData = ctx.getImageData(65, 60, 100, 100);

然后创建一个具有所需大小的辅助画布并使用putImageData 设置像素:

let canvas1 = document.createElement("canvas");
canvas1.width = 100;
canvas1.height = 100;
let ctx1 = canvas1.getContext("2d");
ctx1.rect(0, 0, 100, 100);
ctx1.fillStyle = 'white';
ctx1.fill();
ctx1.putImageData(imageData, 0, 0);

最后使用toDataURL更新图片:

dstImg.src = canvas1.toDataURL("image/png");

CodePen查看我为您准备的完整示例

【讨论】:

  • 好答案。一项改进是使用drawImage 的剪辑版本将原始画布的剪辑部分绘制到canvas1 上。这避免了较慢的.getImageData.putImageData 命令。此外,如果剪辑的图像留在页面上(如果剪辑的图像没有保存到服务器或用户的计算机),您只需将您的 canvas1 添加到 DOM,它就会像 img 元素一样直观地显示。如果原始图像源是跨域的,这将很重要,因为出于安全原因,toDataURLgetImageData 都将被阻止。
  • 感谢您的评论。我完全同意你的看法:)当然使用画布作为 DOM 元素会更好;我只是试图坚持这个问题,不要将 PO 与太多附加信息混淆。出于同样的原因,我对 CORS 只字未提,因为几乎可以肯定图像来自同一个域。
  • @AlexanderDayan - 感谢您给我一个想法。无论如何,您有什么想法可以动态获取 getImageData 的参数吗?就我而言,我使用可调整大小的 div 来确定图像边框。提前致谢。
  • @AlyssaGono 我不确定我是否理解最后一个问题。能否请您详细解释一下您想如何使用它以及您想要达到什么结果?
【解决方案2】:

创建一个目标大小的新画布,使用 drawImage() 在裁剪后的图像中绘制,并将该画布插入 DOM,避免使用 img 和 data-uri:

var ccanvas = document.createElement("canvas"),
    cctx = ccanvas.getContext("2d");

ccanvas.width = w;
ccanvas.height = h;

// draw with crop arguments
cctx.drawImage(image_src,  x, y, w, h,  0, 0, w, h);
//                         ^^^^^^^^^^ source region
//                                      ^^^^^^^^^^ dest. region

// insert cropped image somewhere in the DOM tree:
document.body.appendChild(ccanvas);

window.onload = function() {

  var img = document.getElementById("image_src");

  document.body.appendChild(region2canvas(img, 150, 60, 220, 200));
}

function region2canvas(img, x, y, w, h) {
  var ccanvas = document.createElement("canvas"),
    cctx = ccanvas.getContext("2d");

  ccanvas.width = w;
  ccanvas.height = h;

  // draw with crop arguments
  cctx.drawImage(img, x, y, w, h, 0, 0, w, h);

  return ccanvas;
}
&lt;img src="http://i.imgur.com/kWI4Cmz.png" id="image_src"&gt;

【讨论】:

    【解决方案3】:

    从一张图像进行裁剪的关键是上下文的 drawImage 方法允许我们将源图像的裁剪部分渲染到画布上。

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

    img - 源图像对象
    sx - 源 x
    sy - 来源 y
    sw - 来源宽度
    sh - 源高度
    dx - 目标 x
    dy - 目标 y
    dw - 目标宽度
    dh - 目标高度

    【讨论】:

      【解决方案4】:

      创建一个新画布,并将选定部分复制到该新画布,然后从该新画布获取 toDataURL()。

      【讨论】:

      • 如何将所选部分复制到新画布上?
      • 这并没有解释如何实现这些。
      猜你喜欢
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多