2011-09-06 72 views
8

需要一些幫助。我是一個UI設計師,他不擅長數字化實驗性網頁表單設計,我需要知道哪個輸入元素最接近網頁上的點擊點。我知道如何做點最近的鄰居,但輸入元素是矩形不是點,所以我卡住了。找到離點擊點最近的元素

我正在使用jQuery。我只需要這個小算法的幫助。一旦我完成了我的實驗,我會告訴你們我在做什麼。

UPDATE

我想它是如何可以工作。看該圖:

Nearest

每個矩形具有8個點(或者更確切地說,4個點和4行),這是顯著。只有x值對水平點(紅點)有意義,對於垂直點(綠點)只有y值有意義。 x和y都對角落很重要。

橙色十字是要衡量的點 - 在我的用例中鼠標點擊。淺紫色的線是橙色十字架和可能的最近點之間的距離。

因此...對於任何給定的橙色十字,循環遍歷每個矩形的8個點中的每一個,以找到每個矩形最接近橙色十字的最近的邊或角。具有最低值的矩形是最近的一個。

我可以對它進行概念化和可視化,但不能將其放入代碼中。幫幫我!

+0

使用4點,代表你最近鄰居算法的矩形。或者使用矩形的中心點cx =(left + width)/ 2,cy =(top + height)/ 2。 –

+0

有沒有機會發布一些代碼或在jsfiddle.net中做些什麼?這一切都有點假設,否則... – T9b

+0

增加了一個說明來解釋這個問題以及如何解決它。 –

回答

3

你的算法是正確的。由於您在代碼中需要幫助,而不是算法中,因此代碼如下:

它可能不是最高效的。但它的工作。

// Define the click 
var click = Array(-1, -2); // coodinates in x,y 

// Define the buttons 
// Assuming buttons do not overlap 
var button0 = Array(
    Array(0, 0), // bottom-left point (assuming x is horizontal and y is vertical) 
    Array(6, 6) // upper-right point 
); 

var button1 = Array(
    Array(10, 11), 
    Array(17, 15) 
); 

var button2 = Array(
    Array(-8, -5), 
    Array(-3, -1) 
); 

// Which button to trigger for a click 
i = which(click, Array(button0, button1, button2)); 
alert(i); 


function which(click, buttons){ 
    // Check if click is inside any of the buttons 
    for (i in buttons){ 
     var button = buttons[i]; 
     var bl = button[0]; 
     var tr = button[1]; 

     if ((click[0] >= bl[0] && click[0] <= tr[0]) && 
      (click[1] >= bl[1] && click[1] <= tr[1])){ 
      return i; 
     } 
    } 

    // Now calculate distances 
    var distances = Array(); 

    for (i in buttons){ 
     var button = buttons[i]; 
     var bl = button[0]; 
     var tr = button[1]; 

     if ((click[0] >= bl[0] && click[0] <= tr[0])) { 
      distances[i] = Math.min(Math.abs(click[1]-bl[1]), Math.abs(click[1]-tr[1])); 
     } 
     else if ((click[1] >= bl[1] && click[1] <= tr[1])) { 
      distances[i] = Math.min(Math.abs(click[0]-bl[0]), Math.abs(click[0]-tr[0])); 
     } 
     else{ 
      distances[i] = Math.sqrt(
           (Math.pow(Math.min(Math.abs(click[0]-bl[0]), Math.abs(click[0]-tr[0])), 2)) + 
           (Math.pow(Math.min(Math.abs(click[1]-bl[1]), Math.abs(click[1]-tr[1])), 2)) 
          ); 
     } 
    } 

    var min_id = 0; 
    for (j in distances){ 
     if (distances[j] < distances[min_id]){ 
      min_id = j; 
     } 
    } 

    return min_id; 
} 
+0

太好了。正是我需要的。我如何讓代碼適應任何寬度和高度? –

+1

適用於任何寬度和高度。你只需要定義按鈕的尺寸和JavaScript頂部的點擊座標。 – uzyn

+0

酷感謝的人。 –

2

您可以查找所有矩形的最近角點。這在大多數情況下工作,快速且易於實施。只要你的矩形在一個規則的網格上對齊,這個方法就會給你最近的矩形。

0

我這樣做的方式不是數字,而是邏輯。

我假設你想要的東西,說要結束了,「如果x是那麼最近的元素做一些事情時,我點擊了其他地方,然後做一些X」

你可以做到這一點,如果每個你想要做的事情的元素是簡單的<div>容器,它比你想要處理的元素大,但是不大於它所包含的對象與下一個最近的對象之間的中點。實際上是一個網格。

給所有的容器相同的類。

然後你可以說,「如果點擊y就去做x的事情」,你就已經知道每個容器中的元素了。

我會寫代碼,但我離開工作...

+0

我不想要額外的標記。 –

0

如果你想找到一個2D網格兩點之間的距離,你可以用下面的公式:

(用於2D點A & B)

distanceX =斧 - Bx的

distanceY = Ay的 - B.Ÿ

totalDistance =對squareRoot((distX * distX)+(distY * distY))

一旦你可以檢查兩個點之間的距離,你可以很容易地找出哪些矩形角落你的鼠標點擊最接近太。你可以做很多事情來優化你的預期算法,但是這應該給你一個好的開始。

0

大聲笑,問題是你爲什麼想形狀? 你的問題確實是「如果我點擊一個座標,找到我最近的節點/指向我的點擊」,這是通過各種節點和計算距離的問題。

如果相同的X,Y用差異

如果相同的Y,使用X差異

以其它方式使用hypotheneuse

一旦你找到了,你可以得到父權形狀的最近點? 這會工作,因爲你正試圖對齊最近的點。所以它甚至可以像星星那樣的奇特形狀。

2

加入了相對較新的elementFromPoint()的API讓我們以一種替代,潛在更輕的方法:我們可以點擊測試周圍的鼠標光標,將在更大的圈子,除非我們找到了最近的元素。

我在這裏放了一個快速的非生產示例:http://jsfiddle.net/yRhhs/(Chrome/Safari僅由於使用webkitMatchesSelector)。由於可視化算法中使用的點,性能會變差。

代碼的核心,光性能優化和事件綁定之外,是該位:

function hitTest(x, y){ 
    var element, i = 0; 
    while (!element){ 
     i = i + 7; // Or some other threshold. 

     if (i > 250){ // We do want some safety belts on our while loop. 
      break; 
     } 

     var increment = i/Math.sqrt(2); 
     var points = [ 
      [x-increment, y-increment], [x+increment, y-increment], 
      [x+increment, y+increment], [x-increment, y+increment] 
     ]; 

     // Pop additional points onto the stack as the value of i gets larger. 
     // ... 

     // Perhaps prematurely optimized: we're using Array.prototype.some to bail-out 
     // early once we've found a valid hit target. 
     points.some(function(coordinates){ 
      var hit = document.elementFromPoint.apply(document, coordinates); 
      // isValidHit() could simply be a method that sees whether the current 
      // element matches the kinds of elements we'd like to see. 
      if (isValidHit(hit)){ 
       element = hit; 
       return true; 
      } 
     }); 
}