如何检查鼠标是否在 Canvas 上的十字形上?

How to check if mouse is over a Cross Shape on Canvas?

我正在尝试显示鼠标是否悬停在形成十字形的两条线中的任何一条上现在,如果您将鼠标悬停在'X'[=22 的右下角,它就可以工作=].但并非全部

const x1 = 50;
const y1 = 50;

const x2 = 100;
const y2 = 100;

const xdiff = x2 - x1;
const ydiff = y2 - y1;

function drawX(x, y) {
ctx.beginPath();

ctx.moveTo(x - xdiff, y - ydiff);
ctx.lineTo(x + xdiff, y + ydiff);
ctx.stroke();

ctx.moveTo(x + xdiff, y - ydiff);
ctx.lineTo(x - xdiff, y + ydiff);
ctx.stroke();
}


const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");

 
drawX(x1,y1);

function myFunction(e) {
const x = e.clientX;
const y = e.clientY;
//const coor = "Coordinates: (" + x + "," + y + ")";
const overShape = () => ( (x > x1 && x < (x1 +xdiff)) && (y > y1 && y < (y1 +ydiff)) ) ;

console.log('I am over X, ', overShape() )

}
<canvas id="myCanvas" width="300" height="150" onmousemove="myFunction(event)" style="border:1px solid #d3d3d3;">
  Your browser does not support the HTML5 canvas tag.</canvas>

而不是

const overShape = () => ( (x > x1 && x < (x1 +xdiff)) && (y > y1 && y < (y1 +ydiff)) ) ;

你的边界应该像

一样检查
const overShape = () => ( (x  > (x1 - xdiff) && x < (x1 +xdiff)) && (y > (y1 - ydiff) && y < (y1 +ydiff)) ) ;

const x1 = 50;
const y1 = 50;

const x2 = 100;
const y2 = 100;

const xdiff = x2 - x1;
const ydiff = y2 - y1;

function drawX(x, y) {
  ctx.beginPath();

  ctx.moveTo(x - xdiff, y - ydiff);
  ctx.lineTo(x + xdiff, y + ydiff);
  ctx.stroke();

  ctx.moveTo(x + xdiff, y - ydiff);
  ctx.lineTo(x - xdiff, y + ydiff);
  ctx.stroke();
}


const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");


drawX(x1, y1);

function myFunction(e) {
  const x = e.clientX;
  const y = e.clientY;
  //const coor = "Coordinates: (" + x + "," + y + ")";
  const overShape = () => ((x > (x1 - xdiff) && x < (x1 + xdiff)) && (y > (y1 - ydiff) && y < (y1 + ydiff)));

  console.log('I am over X, ', overShape())

}
<canvas id="myCanvas" width="300" height="150" onmousemove="myFunction(event)" style="border:1px solid #d3d3d3;">
  Your browser does not support the HTML5 canvas tag.</canvas>

您可以通过检查当前鼠标位置的颜色来解决这个问题。如果它是黑色的,你最有可能触摸到 X。当然,如果你的图像中没有任何其他黑色,这只会起作用,所以更好的方法是使用一些数学来完成。

因此,首先将线条的起点和终点定义为单独的点 - 这样我们就可以使用它们进行计算。

const pointA={x:0,y:0};
const pointB={x:100,y:100};
const pointC={x:100,y:0};
const pointD={x:0,y:100};

现在要检查您是否在这四个点形成的直线之一上,您可以使用以下公式:

var treshold=0.01;
var onFirstLine=distance(pointA, mousePosition) + distance(pointB, mousePosition)-distance(pointA, pointB)<treshold;

这里我们将 pointA 和 pointB 到鼠标位置的距离相加,如果结果等于 pointA 到 pointB 的距离,我们就检测到命中。 问题是我们需要非常精确地击中它,这就是我们减去距离并将其与阈值进行比较的原因。

完整示例如下:

const pointA={x:0,y:0};
const pointB={x:100,y:100};
const pointC={x:100,y:0};
const pointD={x:0,y:100};

function drawX(x, y) {
  ctx.beginPath();

  ctx.moveTo(pointA.x, pointA.y);
  ctx.lineTo(pointB.x, pointB.y);
  ctx.stroke();

  ctx.moveTo(pointC.x, pointC.y);
  ctx.lineTo(pointD.x, pointD.y)
  ctx.stroke();
}

const c = document.getElementById("myCanvas");
const ctx = c.getContext("2d");

drawX();

function myFunction(e) {
  var tempPoint = {
    x: e.offsetX,
    y: e.offsetY
  };
  var treshold = 0.01;
  if (distance(pointA, tempPoint) + distance(pointB, tempPoint) - distance(pointA, pointB) < treshold || distance(pointC, tempPoint) + distance(pointD, tempPoint) - distance(pointC, pointD) < treshold) {
    console.log("you're touching X")
  } else {
    console.log("you're NOT touching X")
  }
}

function distance(locPointA, locPointB) {
  return Math.sqrt(Math.pow(locPointB.x - locPointA.x, 2) + Math.pow(locPointB.y - locPointA.y, 2));
}
<canvas id="myCanvas" width="300" height="150" onmousemove="myFunction(event)" style="border:1px solid #d3d3d3;">
  Your browser does not support the HTML5 canvas tag.</canvas>

使用@Kaiido 的解决方案这是解决这个问题的最佳方法

const x1 = 50;
const y1 = 50;

const x2 = 100;
const y2 = 100;

const xdiff = x2 - x1;
const ydiff = y2 - y1;

const threshold = 20;

let path;

function drawX(x, y) {
  path = new Path2D();
  path.moveTo(x - xdiff, y - ydiff);
  path.lineTo(x + xdiff, y + ydiff);
  path.moveTo(x + xdiff, y - ydiff);
  path.lineTo(x - xdiff, y + ydiff);
  ctx.stroke(path);
}


const c = document.getElementById("canvas");
const ctx = c.getContext("2d");


drawX(x1, y1);

canvas.onmousemove = ({
  offsetX,
  offsetY
}) => {
  ctx.lineWidth = threshold;
  console.log('I am over X, ', ctx.isPointInStroke(path, offsetX, offsetY))
}
canvas {
  border: 1px solid #d3d3d3;
  width: 300px;
  height: 150;
}
<canvas id="canvas">
      Your browser does not support the HTML5 canvas tag.</canvas>