javascript 检测鼠标是否在画布内的对象上
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24043967/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detect if Mouse is over an object inside canvas
提问by Dimitra Micha
I have created a line inside a canvas element. I am looking for the easiest way to detect if the position of the mouse is inside the line, which is inside the canvas.
我在画布元素内创建了一条线。我正在寻找最简单的方法来检测鼠标的位置是否在画布内的线内。
I have used this function to see the position of the mouse inside the canvas, but I am very confused on how I should proceed.
我已经使用这个函数来查看鼠标在画布内的位置,但我对应该如何进行感到非常困惑。
function getMousePos(c, evt) {
var rect = c.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
I have also looked at this topic Fabricjs detect mouse over object path, but it detects if the mouse is inside the canvas, not inside the object.
我也看过这个主题Fabricjs 检测鼠标悬停在对象路径上,但它检测鼠标是否在画布内,而不是在对象内。
The line that I create is a part of smaller lines, connected to each other.
我创建的线是较小线的一部分,相互连接。
for (var i = 0; i < 140 ; i++) {
ctx.beginPath();
ctx.moveTo(x[i],y[i]);
ctx.quadraticCurveTo(x[i],50,x[i+1],y[i+1]);
ctx.lineWidth = 40;
ctx.strokeStyle = 'white';
ctx.lineCap = 'round';
ctx.stroke();
}
where x[i] and y[i] are the arrays with the coordinates that I want.
其中 x[i] 和 y[i] 是具有我想要的坐标的数组。
I hope my question is clear, although I am not very familiar with javascript.
我希望我的问题很清楚,尽管我对 javascript 不是很熟悉。
Thanks Dimitra
谢谢迪米特拉
回答by markE
A Demo: http://jsfiddle.net/m1erickson/Cw4ZN/
演示:http: //jsfiddle.net/m1erickson/Cw4ZN/
You need these concepts to check if the mouse is inside a line:
您需要这些概念来检查鼠标是否在一行内:
Define the starting & ending points of a line
Listen for mouse events
On mousemove, check if the mouse is within a specified distance of the line
定义一条线的起点和终点
监听鼠标事件
在 mousemove 上,检查鼠标是否在线的指定距离内
Here's annotated example code for you to learn from.
这是带注释的示例代码供您学习。
$(function() {
// canvas related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
// dom element to indicate if mouse is inside/outside line
var $hit = $("#hit");
// determine how close the mouse must be to the line
// for the mouse to be inside the line
var tolerance = 5;
// define the starting & ending points of the line
var line = {
x0: 50,
y0: 50,
x1: 100,
y1: 100
};
// set the fillstyle of the canvas
ctx.fillStyle = "red";
// draw the line for the first time
draw(line);
// function to draw the line
// and optionally draw a dot when the mouse is inside
function draw(line, mouseX, mouseY, lineX, lineY) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(line.x0, line.y0);
ctx.lineTo(line.x1, line.y1);
ctx.stroke();
if (mouseX && lineX) {
ctx.beginPath();
ctx.arc(lineX, lineY, tolerance, 0, Math.PI * 2);
ctx.closePath();
ctx.fill();
}
}
// calculate the point on the line that's
// nearest to the mouse position
function linepointNearestMouse(line, x, y) {
//
lerp = function(a, b, x) {
return (a + x * (b - a));
};
var dx = line.x1 - line.x0;
var dy = line.y1 - line.y0;
var t = ((x - line.x0) * dx + (y - line.y0) * dy) / (dx * dx + dy * dy);
var lineX = lerp(line.x0, line.x1, t);
var lineY = lerp(line.y0, line.y1, t);
return ({
x: lineX,
y: lineY
});
};
// handle mousemove events
// calculate how close the mouse is to the line
// if that distance is less than tolerance then
// display a dot on the line
function handleMousemove(e) {
e.preventDefault();
e.stopPropagation();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
if (mouseX < line.x0 || mouseX > line.x1) {
$hit.text("Outside");
draw(line);
return;
}
var linepoint = linepointNearestMouse(line, mouseX, mouseY);
var dx = mouseX - linepoint.x;
var dy = mouseY - linepoint.y;
var distance = Math.abs(Math.sqrt(dx * dx + dy * dy));
if (distance < tolerance) {
$hit.text("Inside the line");
draw(line, mouseX, mouseY, linepoint.x, linepoint.y);
} else {
$hit.text("Outside");
draw(line);
}
}
// tell the browser to call handleMousedown
// whenever the mouse moves
$("#canvas").mousemove(function(e) {
handleMousemove(e);
});
}); // end $(function(){});
body {
background-color: ivory;
}
canvas {
border: 1px solid red;
}
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" />
<!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<h2 id="hit">Move mouse near line</h2>
<canvas id="canvas" width=300 height=300></canvas>
</body>
</html>
About hit-testing Paths:
关于命中测试路径:
If you create Paths using path commands you can use context.isPointInPath(mouseX,mouseY) to check if the mouse is inside a path. context.isPointInPath does not work well with lines however because lines theoretically have zero width to "hit".
如果您使用路径命令创建路径,您可以使用 context.isPointInPath(mouseX,mouseY) 来检查鼠标是否在路径内。然而,context.isPointInPath 不能很好地处理线条,因为理论上线条的“命中”宽度为零。