JavaScript drawImage错误地在某些计算机上裁剪源画布图像

时间:2018-02-23 07:39:19

标签: javascript canvas

我的页面上有一个画布,我有一个工具,允许用户选择他/她想要裁剪的区域。它看起来像这样:

enter image description here

要裁剪图像,我计算左上角像素坐标[xmin, ymin]和右下角坐标[xmax,ymax]。裁剪本身就像这样:

context.drawImage(image,xmin,ymin,xmax-xmin,ymax-ymin,0,0,xmax-xmin,ymax-ymin);

问题是,在一些随机计算机和一些随机浏览器上,这段代码会生成正确的块,而另一些则不正确。这就是为什么我甚至无法提供演示或小提琴。在我的笔记本电脑上,在所有浏览器(FF,IE,Opera,Chrome,Safari)上都可以,但在我的用户计算机上它是不正确的。

所以,我的问题是,这次电话会出现什么问题:

context.drawImage(image,xmin,ymin,xmax-xmin,ymax-ymin,0,0,xmax-xmin,ymax-ymin);

有什么东西,我应该考虑使这个代码跨浏览器和跨平台?

1 个答案:

答案 0 :(得分:2)

您的问题是*您的某些用户将其浏览器的缩放级别设置为100%以外的其他用户。

根据您当前的逻辑,您假设图像以原始大小显示,这是drawImage使用的大小。但是当放大或缩小时,浏览器会缩放渲染图像,使光标坐标在图像的自然尺寸方面出错。

为避免这种情况,您需要相对于显示的比例缩放坐标尺寸/自然尺寸。

这是一个简单的例子。

onload = function() {
  const ctx = c.getContext('2d');
  c.width = img.width;
  c.height = img.height;

  img.onmousedown = c.onmousedown = handleMouseDown;
  img.onmousemove = c.onmousemove = handleMouseMove;
  img.onmouseup = c.onmouseup = handleMouseUp;
  
  var rect = { min_x: 0, min_y: 0, max_x: 0, max_y: 0, updating: false};
  
  draw();
  
  function handleMouseDown(evt) {
    evt.preventDefault();
    var targetBB = evt.target.getBoundingClientRect();
    rect.updating = true;
    rect.min_x = rect.max_x = evt.clientX - targetBB.left;
    rect.min_y = rect.max_y = evt.clientY - targetBB.top;
    draw();
  }
  function handleMouseUp(evt) {
    rect.updating = false;
    draw();
  }
  function handleMouseMove(evt) {
    if(!rect.updating) return;
    var targetBB = evt.target.getBoundingClientRect();
    rect.max_x = evt.clientX - targetBB.left;
    rect.max_y = evt.clientY - targetBB.top;
    draw();
  }
  function draw() {
    ctx.filter = 'blur(2px)';
    ctx.drawImage(img, 0,0);
    ctx.filter = 'none';
    var dx = Math.min(rect.min_x, rect.max_x),
      dy = Math.min(rect.min_y, rect.max_y),
      dw = Math.abs(rect.min_x - rect.max_x),
      dh = Math.abs(rect.min_y - rect.max_y);
    if(!dh || !dw) return;
    ctx.strokeRect(dx, dy, dw, dh);
    var ratio_W = img.clientWidth / img.naturalWidth,
      ratio_H = img.clientHeight / img.naturalHeight,
      sx = dx * ratio_W,
      sy = dy * ratio_H,
      sw = dw * ratio_W,
      sh = dh * ratio_H;
    ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh);
  }
}
<h3>Try to zoom-in/out your browser</h3>
<img id="img" src="https://i.stack.imgur.com/ujq5W.png">
<canvas id="c"></canvas>

*根据your comment