2013-01-17 42 views
3

比方说,我在HTML5画布画成这样的行:查找点是否在一条线上

... 
ctx.beginPath(); 
ctx.moveTo(x,y); 
ctx.lineTo(x1,y1); 
ctx.closePath(); 
... 

我想找出是否鼠标点击事件发生在这条线上,而我的代码像这样:

var handleMouseDown = function(e) { 
    var coords = translateCoords(e.x,e.y); 
    ... 
    if (ctx.isPointInPath(coords.x, coords.y) { 
    ... 

现在,这个代码在圈&矩形,而不是行的情况下,罚款。我有两个问题:

  1. 我的想法是,也许在一行上调用closePath()是不正确的。问题 - 如何检查鼠标停止事件是否发生在这条线上?

  2. 我该如何扩展这个以查找是否发生了鼠标向下的事件附近这一行?

回答

7

第一步是找到该点在线上的正常投影。这实际上很简单:从点1到目标的距离,点2到目标,分别称为D1和D2。然后计算D1+(D2-D1)/2。这是从点1到线上投影点的距离。

您现在可以找到该点,并获得从该点到目标的距离。如果距离为零,则目标正好在线上。如果距离小于5,则目标距离小于5px,以此类推。

编辑:一张图片胜过千言万语。这里有一个图:

Diagram http://adamhaskell.net/img/schematic.png

(事后看来,或许应该让那些圈不同的颜色...此外,紫线应该是垂直线AB怪我可怕的宗旨与蓝色行!)

+0

谢谢 - 梦幻般的答案,真的很感谢你的帮助! – appa

+1

嗯,虽然这对线条很好用,但我想我需要一个不同的解决方案来处理其他一维路径,例如弧线或曲线。下面的解决方案可能会更好地工作。 – appa

1

你有两个选择。您的“简单”选项是使用画布来完成它 - 无论鼠标位于何处,都可以读取像素数据,并且与您的线条颜色相同,然后用户点击该线条。然而,这会产生很多假设,就像您的画布上的所有内容都以不同的纯色呈现。然而,这是可能的,因为常见的技巧是将所有内容以不同的纯色呈现在屏幕外。然后,当用户通过读取一个像素的颜色并将其映射回原始对象来单击某件事物时,您确切知道它是什么。

但是,这不是你问什么了:)

你不想知道,如果用户上线,因为他们几乎永远不会点击。一条线是无限薄的,所以除非它完全水平或完全垂直,否则它们将永远不会点击它。你想要的是看看鼠标离线有多远。 Kolink只是回答那一部分,所以我会停在这里:)

+0

谢谢 - 我应该考虑使用一个屏幕画布来表现我正在做的事情,而我目前还没有这样做。 – appa

2

下面是来自维基百科的文章所采取的办法Distance from a point to a line (Line defined by two points)

 var Dx = x2 - x1; 
     var Dy = y2 - y1; 
     var d = Math.abs(Dy*x0 - Dx*y0 - x1*y2+x2*y1)/Math.sqrt(Math.pow(Dx, 2) + Math.pow(Dy, 2)); 

其中(X0,Y0)是你的点坐标和你的线是(( x1,y1),(x2,y2)) 但是,这并不检查行的边界,所以我不得不添加另一个检查。

function inBox(x0, y0, rect) { 
     var x1 = Math.min(rect.startX, rect.startX + rect.w); 
     var x2 = Math.max(rect.startX, rect.startX + rect.w); 
     var y1 = Math.min(rect.startY, rect.startY + rect.h); 
     var y2 = Math.max(rect.startY, rect.startY + rect.h); 
     return (x1 <= x0 && x0 <= x2 && y1 <= y0 && y0 <= y2); 
    } 

你的线条定义为矩形的地方。希望这可以帮助。