使用 canvas 绘制一个固定宽度的矩形

Draw a rectangle using canvas with a fixed width

我试图让用户使用 mousemove 事件在 canvas 内的图像上绘制一个矩形。它适用于此代码:

HTML:

    <canvas id="canvas"></canvas>

JavaScript:

window.onload = drawCanvas('http://www.therebeldandy.com/wp-content/uploads/2016/09/Menswear-Dog-4.jpg');

var context = canvas.getContext('2d');

function drawCanvas(src) {

    var rect = {};
    var drag = false;
    var img = new Image();
    var canvas = document.getElementById('canvas');

    img.src = src;
    img.addEventListener('load', function () {
        canvas.width = img.naturalWidth;
        canvas.height = img.naturalHeight;
        context.drawImage(img, 0, 0);
    }, false);

    // Draw user selection
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);

    function mouseDown(e) {
        rect.startX = e.pageX - this.offsetLeft;
        rect.startY = e.pageY - this.offsetTop;
        drag = true;
    }

    function mouseUp() {
        drag = false;
    }

    function mouseMove(e) {
        if (drag) {
            context.clearRect(0, 0, 500, 500);
            context.drawImage(img, 0, 0);
            rect.w = (e.pageX - this.offsetLeft) - rect.startX;
            rect.h = (e.pageY - this.offsetTop) - rect.startY;
            context.lineWidth = 3;
            context.strokeStyle = '#df4b26';
            context.fillStyle = "rgba(255, 255, 255, .25)";
            context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
            context.fillRect(rect.startX, rect.startY, rect.w, rect.h);
            console.log(rect.startX, rect.startY, rect.w, rect.h);
        }
    }

}

问题是我需要确保图像具有固定宽度,所以我使用 HTML 代替:

<canvas id="canvas" style="max-width: 300px; height: auto;"></canvas>

仅仅添加这个样式就破坏了整个事情:我不能再 select 我想要的图像部分了。

这里有一个 fiddle 可以让您更好地理解我要完成的工作:JSFiddle

有没有办法让它工作?我已经苦苦挣扎了几个小时,所以我们将不胜感激。

不幸的是,正如您发现的那样,CSS 调整尺寸会破坏 canvas 图纸。如果我理解您所追求的结果,您希望可变高度和固定宽度与缩放以适合的源图像。这段代码改编自 ,应该这样做:

  var width = 500; // specify your fixed width here
  var h;
  var w;
  var scale;

  img.addEventListener('load', function() {
    h = img.naturalHeight;
    w = img.naturalWidth;
    scale = Math.min(width / w, width / h);
    canvas.width = width;
    canvas.height = h * scale;
    context.drawImage(img, 0, 0, w, h, 0, 0, w * scale, h * scale);
  }, false);
  img.src = src;

请注意,我还更改了第二个 contex.drawImage() 调用以匹配您代码中的上述调用。这是更新后的代码:

window.onload = drawCanvas('https://i.ndtvimg.com/i/2016-10/spud-boxer-best-dressed-dog_650x400_41476182056.jpg');

var context = canvas.getContext('2d');

function drawCanvas(src) {
  var rect = {};
  var drag = false;
  var img = new Image();
  var canvas = document.getElementById('canvas');

  img.addEventListener('load', function () {
    canvas.width = img.naturalWidth;
    canvas.height = img.naturalHeight;
    context.drawImage(img, 0, 0);
  }, false);
  img.src = src;

  // Draw user selection if image is loaded
  canvas.addEventListener('mousedown', mouseDown, false);
  canvas.addEventListener('mouseup', mouseUp, false);
  canvas.addEventListener('mousemove', mouseMove, false);

  function mouseDown(e) {
    rect.startX = e.pageX - this.offsetLeft;
    rect.startY = e.pageY - this.offsetTop;
    drag = true;
  }

  function mouseUp() {
    drag = false;
  }

  function mouseMove(e) {
    if (drag) {
      context.clearRect(0, 0, 500, 500);
      context.drawImage(img, 0, 0);
      rect.w = (e.pageX - this.offsetLeft) - rect.startX;
      rect.h = (e.pageY - this.offsetTop) - rect.startY;
      context.lineWidth = 3;
      context.strokeStyle = '#df4b26';
      context.fillStyle = "rgba(255, 255, 255, .25)";
      context.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
      context.fillRect(rect.startX, rect.startY, rect.w, rect.h);
      console.log(rect.startX, rect.startY, rect.w, rect.h);
    }
  }
}

document.getElementById("button").onclick = function() {
  changeImg();
};

function changeImg() {
  //context.clearRect(0, 0, canvas.width, canvas.height);
  drawCanvas("http://www.therebeldandy.com/wp-content/uploads/2016/09/Menswear-Dog-4.jpg");
}
<canvas id="canvas" style="max-width: 300px; height: auto;"></canvas>
<br />
<button id="button">ChangeImage</button>

问题出在这里:

canvas.width = img.naturalWidth

改成这样:

img.addEventListener('load', function() {
  canvas.width = width;
  canvas.height = img.naturalHeight;
  context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, width, img.naturalHeight); 
}, false);`

并将宽度设置为变量

 var width = 500;

同时将mouseMove函数中的drawImage修改为:

  context.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, width, img.naturalHeight);

并保持 canvas 原样:

  <canvas id="canvas" style="max-width: 100%; height: auto;"></canvas>

js 小提琴 here