需要一些帮助。我是一名UI设计师,他不擅长做实验性Web表单设计的数字,我需要知道哪个输入元素最接近网页上的点击点。我知道如何用点做近邻,但输入元素是矩形而不是点,所以我被卡住了。
我正在使用jQuery。我只需要帮助这个小算法。一旦我完成了我的实验,我会告诉你们我正在做什么。
更新
我想过它是如何运作的。看看这个图:
每个矩形有8个点(或者更确切地说是4个点和4个线)。只有x值对于水平点(红点)才有意义,只有y值对于垂直点(绿点)才有意义。 x和y都是角落的重要部分。
橙色十字架是要测量的点 - 在我的用例中点击鼠标。浅紫色线是橙色十字和它可能的最近点之间的距离。
所以...对于任何给定的橙色十字,循环遍历每个矩形的8个点中的每一个,以找到每个矩形最接近橙色十字的最近边或角。值最小的矩形是最接近的矩形。
我可以对其进行概念化和可视化,但不能将其置于代码中。救命!
答案 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;
}
答案 1 :(得分:3)
添加相对较新的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;
}
});
}
答案 2 :(得分:2)
您可以查找所有矩形的最近角点。这种方法在大多数情况下都可以实现,并且快速且易于实施。只要您的矩形在规则网格上对齐,此方法就会为您提供最近的矩形。
答案 3 :(得分:0)
我这样做的方式不是数字,而是逻辑。
我假设你想要最终得到的结论是,“如果x是最接近的元素,那么当我点击其他地方时再做一些事情然后对x做一些事情”
如果你想要做的每个元素都在简单的<div>
容器中,你可以做到这一点,这个容器比你想要处理的元素大,但是它不包含它所包含的对象之间的中间位置。下一个最近的对象事实上是一个网格。
为所有容器提供相同的类。
然后你可以说,“如果你点击y去做x的事情”,你就会知道每个容器中有哪个元素。
我会写代码,但我要离开工作......
答案 4 :(得分:0)
如果要在2D网格上找到两点之间的距离,可以使用以下公式:
(对于2D点A和B)
distanceX = A.x - B.x
distanceY = A.y - B.y
totalDistance = squareRoot((distX * distX)+(distY * distY))
一旦你可以检查两点之间的距离,你就可以很容易地找出鼠标点击哪个矩形角也是最近的。您可以采取许多措施来优化预期的算法,但这应该会给您一个良好的开端。
答案 5 :(得分:0)
如果相同X,请使用y差异
如果相同y,请使用x difference
否则使用假设
找到最近点后,您可以获得父形状吗? 这将有效,因为您试图捕捉到最近点。所以它甚至可以用于像星星这样的奇特形状。