画布上可移动选区

问题描述 投票:0回答:1

下面是如何通过拖放在

<canvas>
上绘制“选择矩形”,请参阅如何在 HTML 画布上通过拖放绘制选择矩形?

是否有一种简单的方法可以检测悬停在几个像素距离处的选择矩形,并允许通过拖放来移动选择矩形?

var c1 = document.getElementById("c1"), c2 = document.getElementById("c2");
var ctx1 = c1.getContext("2d"), ctx2 = c2.getContext("2d");
ctx2.setLineDash([5, 5]);
var origin = null;
window.onload = () => { ctx1.drawImage(document.getElementById("img"), 0, 0); }
c2.onmousedown = e => { origin = {x: e.offsetX, y: e.offsetY}; };
window.onmouseup = e => { origin = null; };
c2.onmousemove = e => { 
    if (!!origin) { 
        ctx2.strokeStyle = "#ff0000";
        ctx2.clearRect(0, 0, c2.width, c2.height);
        ctx2.beginPath();
        ctx2.rect(origin.x, origin.y, e.offsetX - origin.x, e.offsetY - origin.y); 
        ctx2.stroke(); 
    } 
};
#img { display: none; }
#canvas-container { position: relative; }
canvas { position: absolute; left: 0; top: 0; }
#c1 { z-index: 0; }
#c2 { z-index: 1; }
<img id="img" src="https://i.imgur.com/okSIKkW.jpg">
<div id="canvas-container">
<canvas id="c1" height="200" width="200"></canvas>
<canvas id="c2" height="200" width="200"></canvas>
</div>

javascript html canvas selection
1个回答
2
投票

存储当前选择

为了能够移动现有的选择,您必须保存其状态。现在,您的代码在绘制一次后就会“忘记”它。

您可以将您的选择保存在

mouseup
上的变量中,如下所示:

const dx = origin.x - mouse.x;
const dy = origin.y - mouse.y;

selection = {
  left:   Math.min(mouse.x, origin.x),  
  top:    Math.min(mouse.y, origin.y),
  width:  Math.abs(dx),
  height: Math.abs(dy)
}

交叉路口检查

您的选择是一个矩形。您可以像这样检查鼠标是否与矩形相交:

const intersects = (
  mouse.x >= selection.left &&
  mouse.x <= selection.left + selection.width &&
  mouse.y >= selection.top &&
  mouse.y <= selection.top + selection.height
);

如果您想在矩形周围添加一些填充,您可以将复选框更改为,例如,

mouse.x >= selection.left - PADDING

制作或移动

您现在必须支持两种类型的交互:

  1. 做出新选择,并且
  2. 移动现有选择

这是我的实现有点混乱的地方,但你可以自己重构它🙂

除了将选择保存到变量之外,我没有对选择代码进行太多更改。

移动选区时,您可以拖动鼠标拖动

dx
dy
,并将它们添加到选区的 原始 位置 (
ox, oy
):

const dx = origin.x - mouse.x;
const dy = origin.y - mouse.y;

selection.left = ox - dx;
selection.top = oy - dy;

这是可运行片段中的所有内容:

var c1 = document.getElementById("c1"),
    c2 = document.getElementById("c2");
var ctx1 = c1.getContext("2d"),
    ctx2 = c2.getContext("2d");
  
ctx2.setLineDash([5, 5]);

var origin = null;
let selection = null;
let selectionHovered = false;
let interaction = null;
let ox = null;
let oy = null;

window.onload = () => { ctx1.drawImage(document.getElementById("img"), 0, 0); }

c2.onmousedown = e => { 
  origin = {x: e.offsetX, y: e.offsetY};
  
  if (selectionHovered) {
    interaction = "MOVE_SELECTION";
    ox = selection.left;
    oy = selection.top;
  } else {
    interaction = "MAKE_SELECTION";
  }
  
};

window.onmouseup = e => {
  interaction = null;
  origin = null;
};

c2.onmousemove = e => {
  const x = e.offsetX;
  const y = e.offsetY;
  
  if (!interaction) {
   selectionHovered = (
      selection &&
      x >= selection.left &&
      x <= selection.left + selection.width &&
      y >= selection.top &&
      y <= selection.top + selection.height
    );
  } else {
    const dx = origin.x - x;
    const dy = origin.y - y;

    // Update
    switch (interaction) {
      case "MOVE_SELECTION":
        selection.left = ox - dx;
        selection.top = oy - dy;

        break;
      case "MAKE_SELECTION":
        selection = {
          left:   Math.min(x, origin.x),
          top:    Math.min(y, origin.y),
          width:  Math.abs(dx),
          height: Math.abs(dy)
        }
        break
      default:
        // Do nothing
    }


    // Set selectionHovered
    if (selection) {

    } else {
      selectionHovered = false;
    }
  }

  // Draw
  if (selection) drawSelection(selection);
};

function drawSelection({ top, left, width, height }) {
  // Draw rect
  ctx2.strokeStyle = "#ff0000";
  ctx2.clearRect(0, 0, c2.width, c2.height);
  ctx2.beginPath();
  ctx2.rect(left, top, width, height); 
  ctx2.stroke(); 
  
  // Set mouse 
  c2.style.cursor = selectionHovered ? "move" : "default";
  
}
#img { display: none; }
body { margin: 0; }
#canvas-container { position: relative; }
canvas { position: absolute; left: 0; top: 0; }
#c1 { z-index: 0; }
#c2 { z-index: 1; }
<img id="img" src="https://i.imgur.com/okSIKkW.jpg">
<div id="canvas-container">
  <canvas id="c1" height="200" width="200"></canvas>
  <canvas id="c2" height="200" width="200"></canvas>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.