web-dev-qa-db-ja.com

DOM要素の画面座標を取得する

どういうわけか、DOMオブジェクトの(画面の左上隅を基準とした)正確な画面座標を取得できますか? NPAPI\FireBreathまたはJavaScriptを介して。 (これはプラグインに必要です。FireBreathで作成しています)

11
Max Yari

カーソルをページのどこかに移動し、クリックイベントを作成します(ウィンドウを見つけ、次にGetWindowRectを実行し、適切な位置を計算します)。次に、イベントをキャッチし、clientXとclientYを記録します。これにより、2つの異なる座標系の間に橋をかけます。

1
Jason Zheng

PS:私はずっと前にこの質問をしたことを知っていますが、最後に得たものを要約したいと思います。

_element.offsetLeft\Top_は、問題となっているとおりには機能しません。
HTMLから、ユーザー画面自体ではなく、ページのスペースの左上隅を基準にした座標を取得できます。

プラグインから、GetWindowRect() winAPI関数を使用すると、ユーザーウィンドウを基準としたブラウザウィンドウの左上隅の座標を取得でき、GetClientRect()を使用すると、左上隅の座標を取得できますクライアント長方形の角。

しかし、それはページの左上と同じポイントではありません、ページのスペースのコーナーとクライアントの四角形、またはウィンドウの四角形の間には常に何かがあります。トップブラウザバーやその他のものを含みます。

あなたは何ができますか?簡単に100%制御できる方法はないようです。

これらのブラウザーバーを検討して_Client rect_とページの四角形の間のスペースを計算することはできますが、これらのブラウザーバーはユーザーごとに一定ではなく、1つ以上のブラウザーバーを持つことができ、すべての座標を取得できますシステムが台無しに。次に、ブラウザーにインストールされているバーと追加の量を何らかの方法で登録し、その計算によると、それらが消費するスペースの量を計算できますが、バーと追加は同じではなく、考慮すべき変数が多すぎます。

少し簡単な方法があります。上からではなく、下から行くことができます-長方形の最下点の座標を取得し、HTMLの_element.offset_を使用していくつかの計算を介して-座標系を左下の点にバインドします窓。
下部にユーザーのブラウザーバーがないため、ページとウィンドウコーナーの間のスペースに少し自信がありますが、一部のブラウザーにはダウンロード情報などのポップアップバーがあり、ここにすべてが表示されます再びめちゃくちゃ。

別のオプションは、モーダルウィンドウを使用することです。つまり、JavaScriptからwindow.open()を使用してモーダルウィンドウでページを開き、それらのウィンドウのブラウザーコントロールとバーの量を制御し、それらすべてのユーザーバーを削除して、アドレスバーとページのみが表示された明確なウィンドウ。これで、より多くの制御が可能になり、ほぼ確実に、コーナー間のこのスペースがすべてのユーザーで同じになることをほぼ確認できます。
言及する必要がある2つの事柄があります:

1)一部のブラウザー(たとえば、覚えているようにgoogle chromeなど)では、カスタムブラウザーの追加(Firebugなど)がアドレスバーの近くに小さなアイコンとして表示されますが、モーダルウィンドウのアドレスバーの近くにはまだ表示されます。
どのような違いを求めることができますか-違いは、それらのアイコンが1つでもある場合、何らかの理由でブラウザウィンドウの上部が約5ピクセル太くなることです(ここでも登録してみてください。ユーザーのブラウザにインストールされているものがあるかどうか)
そして、とにかく、これらの5pxがあなたにとって重要ではない場合-それは行く方法になる可能性があります...次のことに問題がない場合.

2)明白なもの-モーダルウィンドウのその楽しさは、エンドユーザーにとって不快なものになる可能性があります。これは、ブラウザーユーザーが慣れている一部のブラウザーコントロールと機構をカットするためです。

7
Max Yari

JQueryについて言及しなかったのはわかっていますが、例として http://api.jquery.com/offset/ を使用できます。 offsetLeft/topすべての親のスクロールおよびスクロールを考慮し、ネストされたノードの正確なx、y(本文に対して)を提供します。

イベントを処理している場合、イベントオブジェクトは常に http://api.jquery.com/event.pageX/http://を使用してイベントが発生した場所を通知しますapi.jquery.com/event.pageY/

繰り返しになりますが、jQueryについて言及するのは、それを使用したくない場合にのみインスピレーションを得るためです。

JQueryが行う方法は次のとおりです

$.fn.offset = function (options) {
    var elem = this[0],
        doc = elem && elem.ownerDocument;

    if (!doc) {
        return null;
    }

    if (elem === doc.body) {
        return jQuery.offset.bodyOffset(elem);
    }

    return getOffset(elem, doc, doc.documentElement);
}

function getOffset(elem, doc, docElem, box) {
    try {
        box = elem.getBoundingClientRect();
    } catch(e) {}

    // Make sure we're not dealing with a disconnected DOM node
    if (!box || !jQuery.contains(docElem, elem)) {
        return box ? {
            top: box.top,
            left: box.left
        } : {
            top: 0,
            left: 0
        };
    }

    var body = doc.body,
        win = getWindow(doc),
        clientTop = docElem.clientTop || body.clientTop || 0,
        clientLeft = docElem.clientLeft || body.clientLeft || 0,
        scrollTop = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop || body.scrollTop,
        scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
        top = box.top + scrollTop - clientTop,
        left = box.left + scrollLeft - clientLeft;

    return {
        top: top,
        left: left
    };
}
5
Juan Mendes