2013-01-17 70 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); 
    } 

你的線條定義爲矩形的地方。希望這可以幫助。