8

ここで助けが必要です。私は実験的な Web フォーム デザインを行う数字が苦手な UI デザイナーであり、Web ページでクリックされたポイントに最も近い入力要素を知る必要があります。ポイントで最近傍を行う方法は知っていますが、入力要素はポイントではなく長方形であるため、行き詰まっています。

私はjQueryを使用しています。この小さなアルゴについて助けが必要です。実験が終わったら、私が何をしているかを皆さんにお見せします。

アップデート

どうすればうまくいくかを考えました。この図を見てください:

最寄り

各長方形には、重要な 8 つのポイント (または 4 つのポイントと 4 つの線) があります。水平点 (赤い点) では x 値のみが重要であり、垂直点 (緑色の点) では y 値のみが重要です。コーナーでは x と y の両方が重要です。

Orange crosses are the points to be measured against – mouse clicks in my use case. The light purple lines are the distances between the orange cross and it's possible nearest point.

So… for any given orange cross, loop through each of the 8 points n every rectangle to find the nearest edge or corner closest of each rectangle to the orange cross. The rectangle with the lowest value is the nearest one.

I can conceptualize and visualize it but can't put it into code. Help!

4

6 に答える 6

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;
}
于 2011-09-09T11:06:21.300 に答える
3

比較的新しいelementFromPoint() API を追加することで、代替のより軽量なアプローチを取ることができます。マウス カーソルの周りでテストをヒットし、最も近い要素が見つかるまで大きな円を描くことができます。

ここに簡単な非実稼働の例をまとめました: http://jsfiddle.net/yRhhs/ (webkitMatchesSelector を使用するため、Chrome/Safari のみ)。アルゴリズムの視覚化に使用されるドットが原因で、パフォーマンスが遅くなる可能性があります。

ライト パフォーマンスの最適化とイベント バインディング以外のコードのコアは、次のビットです。

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;
            }
       });
}
于 2013-10-18T22:29:32.480 に答える
2

すべての長方形の最も近い角点を探すことができます。これはほとんどの場合に機能し、迅速かつ簡単に実装できます。長方形が通常のグリッド上に配置されている限り、このメソッドは最も近い長方形を提供します。

于 2011-09-06T15:44:15.777 に答える
0

笑、質問はなぜあなたは形を考えているのですか?あなたの質問は、実際には「座標をクリックした場合、クリックに最も近いノード/ポイントを見つけてください」です。これは、さまざまなノードを通過して距離を計算することです。

同じXの場合、yの差を使用します

同じyの場合、xの差を使用します

それ以外の場合は斜辺を使用します

最も近い点を見つけたら、親の形を正しくすることができますか?これは、最も近いポイントにスナップしようとしているために機能します。そのため、星のような派手な形でも機能します。

于 2011-09-07T15:32:45.057 に答える
0

2D グリッド上の 2 点間の距離を求める場合は、次の式を使用できます。

(2D ポイント A & B の場合)

距離X = Ax - Bx

距離 Y = Ay - By

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

2 点間の距離を確認できれば、マウスでクリックした四角形の角が最も近いかどうかも簡単にわかります。意図したアルゴリズムを最適化するためにできることはたくさんありますが、これで良いスタートが切れるはずです。

于 2011-09-07T15:30:35.503 に答える
0

私がやりたいのは、数字ではなく論理です。

「xが最も近い要素である場合、他の場所をクリックしたときに何かを実行してから、xに何かを実行する」という結果になりたいと想定しています。

何かをしたい要素のそれぞれが、<div>処理したい要素よりも大きいが、含まれているオブジェクトと次に近いオブジェクトの中間よりも大きくない単純なコンテナーにある場合に、これを行うことができます。実際にはグリッド。

すべてのコンテナに同じクラスを与えます。

次に、「y がクリックされた場合、x に対して何かを実行します」と言うことができます。各コンテナーにどの要素が含まれているかは既にわかっています。

コードを書きたいのですが、仕事を辞めます...

于 2011-09-06T15:52:17.380 に答える