1995

JavaScriptのimgやなどの HTML 要素の X と Y の位置を取得する方法を知りたいです。div

4

29 に答える 29

2190

正しいアプローチは、次を使用することelement.getBoundingClientRect()です。

var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);

Internet Explorer は、気にする可能性が高い限り、これをサポートしており、最終的にCSSOM Viewsで標準化されました。他のすべてのブラウザは、ずっと前にそれを採用していました。

高さと幅のプロパティを返すブラウザもありますが、これは標準ではありません。古いブラウザーの互換性が心配な場合は、最適化された劣化実装について、この回答のリビジョンを確認してください。

によって返される値はelement.getBoundingClientRect()、ビューポートに相対的です。別の要素に対して相対的に必要な場合は、単純に一方の長方形をもう一方から引きます。

var bodyRect = document.body.getBoundingClientRect(),
    elemRect = element.getBoundingClientRect(),
    offset   = elemRect.top - bodyRect.top;

alert('Element is ' + offset + ' vertical pixels from <body>');
于 2012-07-09T14:06:24.990 に答える
355

ライブラリは、要素の正確なオフセットを取得するためにある程度の時間を費やします。
これは、私が試したすべての状況で機能する単純な関数です。

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}
var x = getOffset( document.getElementById('yourElId') ).left; 
于 2009-01-14T10:04:45.700 に答える
352

この関数は、ドキュメント (ページ) 全体に対する要素の位置を返します。

function getOffset(el) {
  const rect = el.getBoundingClientRect();
  return {
    left: rect.left + window.scrollX,
    top: rect.top + window.scrollY
  };
}

これを使用して、X 位置を取得できます。

getOffset(element).left

... または Y 位置:

getOffset(element).top
于 2015-01-29T18:46:34.720 に答える
149

javascript のみで実行したい場合は、次のライナー を使用しますgetBoundingClientRect()

window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y

window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X

offsetTop最初の行は、ドキュメントに相対的な Yを返します。offsetLeft2 行目は、ドキュメントに相対的な Xを返します。

getBoundingClientRect()ウィンドウのビューポートに対する要素の位置を返す JavaScript 関数です。

于 2018-09-24T10:41:35.573 に答える
56

ほとんどのブラウザの HTML 要素には次のものがあります:-

offsetLeft
offsetTop

これらは、レイアウトを持つ最も近い親に対する要素の位置を指定します。多くの場合、この親は、offsetParent プロパティを介してアクセスできます。

IEとFF3は

clientLeft
clientTop

これらのプロパティはあまり一般的ではなく、親のクライアント領域で要素の位置を指定します (パディング領域はクライアント領域の一部ですが、ボーダーとマージンはそうではありません)。

于 2009-01-14T09:43:14.387 に答える
38

ページに少なくとも「DIV」が含まれている場合、meouw によって指定された関数は、現在のページ制限を超えて「Y」値をスローします。正確な位置を見つけるには、offsetParent と parentNode の両方を処理する必要があります。

以下のコードを試してください (FF2 でチェックされます):


var getAbsPosition = function(el){
    var el2 = el;
    var curtop = 0;
    var curleft = 0;
    if (document.getElementById || document.all) {
        do  {
            curleft += el.offsetLeft-el.scrollLeft;
            curtop += el.offsetTop-el.scrollTop;
            el = el.offsetParent;
            el2 = el2.parentNode;
            while (el2 != el) {
                curleft -= el2.scrollLeft;
                curtop -= el2.scrollTop;
                el2 = el2.parentNode;
            }
        } while (el.offsetParent);

    } else if (document.layers) {
        curtop += el.y;
        curleft += el.x;
    }
    return [curtop, curleft];
};

于 2010-08-12T20:14:33.160 に答える
36

2 つのプロパティを追加しElement.prototypeて、任意の要素の上/左を取得できます。

Object.defineProperty( Element.prototype, 'documentOffsetTop', {
    get: function () { 
        return this.offsetTop + ( this.offsetParent ? this.offsetParent.documentOffsetTop : 0 );
    }
} );

Object.defineProperty( Element.prototype, 'documentOffsetLeft', {
    get: function () { 
        return this.offsetLeft + ( this.offsetParent ? this.offsetParent.documentOffsetLeft : 0 );
    }
} );

これは次のように呼び出されます。

var x = document.getElementById( 'myDiv' ).documentOffsetLeft;

結果をjQueryのものoffset().topと比較するデモがあり.leftます:http://jsfiddle.net/ThinkingStiff/3G7EZ/

于 2012-01-14T08:57:16.677 に答える
26

再帰関数を使用せずに、ページに対する相対的な位置を効率的に取得するには: (IE も含む)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.
var rect = element.getBoundingClientRect();
var elementLeft,elementTop; //x and y
var scrollTop = document.documentElement.scrollTop?
                document.documentElement.scrollTop:document.body.scrollTop;
var scrollLeft = document.documentElement.scrollLeft?                   
                 document.documentElement.scrollLeft:document.body.scrollLeft;
elementTop = rect.top+scrollTop;
elementLeft = rect.left+scrollLeft;
于 2013-07-26T01:49:09.877 に答える
17

jQuery .offset()は、ドキュメントを基準にして、最初の要素の現在の座標を取得するか、一致した要素のセット内のすべての要素の座標を設定します。

于 2010-08-18T14:43:35.537 に答える
16

ブラウザーに依存しない方法で、そのような情報 (およびその他の情報) を返す関数を備えた JavaScript フレームワークを使用すると、より適切なサービスが提供される場合があります。ここにいくつかあります:

これらのフレームワークを使用すると、次のようなことができます: $('id-of-img').top 画像の y ピクセル座標を取得します。

于 2009-01-14T09:47:21.337 に答える
11

私は@meouwの答えを取り、境界線を可能にするclientLeftに追加してから、3つのバージョンを作成しました:

getAbsoluteOffsetFromBody - @meouw のものと同様に、ドキュメントの body または html 要素に対する絶対位置を取得します (quirks モードによって異なります)。

getAbsoluteOffsetFromGivenElement - 指定された要素 (relativeEl) に対する絶対位置を返します。指定された要素には要素 el が含まれている必要があることに注意してください。そうでない場合、これは getAbsoluteOffsetFromBody と同じように動作します。これは、別の (既知の) 要素 (オプションでノード ツリーのいくつかのノード) 内に含まれる 2 つの要素があり、それらを同じ位置に配置したい場合に便利です。

getAbsoluteOffsetFromRelative - position: relative を持つ最初の親要素に対する絶対位置を返します。これは同じ理由で getAbsoluteOffsetFromGivenElement に似ていますが、最初に一致した要素までしか進みません。

getAbsoluteOffsetFromBody = function( el )
{   // finds the offset of el from the body or html element
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromGivenElement = function( el, relativeEl )
{   // finds the offset of el from relativeEl
    var _x = 0;
    var _y = 0;
    while( el && el != relativeEl && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
    }
    return { top: _y, left: _x };
}

getAbsoluteOffsetFromRelative = function( el )
{   // finds the offset of el from the first parent with position: relative
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) )
    {
        _x += el.offsetLeft - el.scrollLeft + el.clientLeft;
        _y += el.offsetTop - el.scrollTop + el.clientTop;
        el = el.offsetParent;
        if (el != null)
        {
            if (getComputedStyle !== 'undefined')
                valString = getComputedStyle(el, null).getPropertyValue('position');
            else
                valString = el.currentStyle['position'];
            if (valString === "relative")
                el = null;
        }
    }
    return { top: _y, left: _x };
}

特にスクロールに関連する問題が解決しない場合は、http: //www.greywyvern.com/?post=331 を参照してください。getStyle に問題のあるコードが少なくとも 1 つあることに気付きました。 、しかし残りはまったくテストしていません。

于 2015-12-01T07:24:49.480 に答える
8

jQuery を使用している場合、ディメンション プラグインは優れており、必要なものを正確に指定できます。

例えば

相対位置、絶対位置、パディングなしの絶対位置、パディングあり...

それは続きます、それでできることはたくさんあるとだけ言っておきましょう。

さらに、jQuery を使用する利点は、ファイル サイズが軽量で使いやすいことです。後で jQuery なしでは JavaScript に戻れません。

于 2009-01-14T10:24:21.603 に答える
6

これは私が作成した中で最高のコードです (jQuery の offset() とは異なり、iframe でも機能します)。webkit の動作は少し異なるようです。

meouw のコメントに基づく:

function getOffset( el ) {
    var _x = 0;
    var _y = 0;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        // chrome/safari
        if ($.browser.webkit) {
            el = el.parentNode;
        } else {
            // firefox/IE
            el = el.offsetParent;
        }
    }
    return { top: _y, left: _x };
}
于 2011-09-10T17:05:08.647 に答える
2

Andy E のソリューションを使用して、ユーザーがクリックしたテーブル行のリンクに応じて、ブートストラップ 2 モーダルを配置することに成功しました。このページは Tapestry 5 のページで、Java ページ クラスに以下の JavaScript がインポートされています。

JavaScript:

function setLinkPosition(clientId){
var bodyRect = document.body.getBoundingClientRect(),
elemRect = clientId.getBoundingClientRect(),
offset   = elemRect.top - bodyRect.top;
offset   = offset + 20;
$('#serviceLineModal').css("top", offset);

}

私のモーダルコード:

<div id="serviceLineModal" class="modal hide fade add-absolute-position" data-backdrop="static" 
 tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="top:50%;">
<div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-hidden="true">x</button>
    <h3 id="myModalLabel">Modal header</h3>
</div>

<div class="modal-body">
    <t:zone t:id="modalZone" id="modalZone">
        <p>You selected service line number: ${serviceLineNumberSelected}</p>
    </t:zone>
</div>

<div class="modal-footer">
    <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
    <!-- <button class="btn btn-primary">Save changes</button> -->
</div>

ループ内のリンク:

<t:loop source="servicesToDisplay" value="service" encoder="encoder">
<tr style="border-right: 1px solid black;">       
    <td style="white-space:nowrap;" class="add-padding-left-and-right no-border"> 
        <a t:type="eventLink" t:event="serviceLineNumberSelected" t:context="service.serviceLineNumber" 
            t:zone="pageZone" t:clientId="modalLink${service.serviceLineNumber}"
            onmouseover="setLinkPosition(this);">
            <i class="icon-chevron-down"></i> <!-- ${service.serviceLineNumber} -->
        </a>
    </td>

ページ クラスの Java コード:

void onServiceLineNumberSelected(String number){
    checkForNullSession();
    serviceLineNumberSelected = number;
    addOpenServiceLineDialogCommand();
    ajaxResponseRenderer.addRender(modalZone);
}

protected void addOpenServiceLineDialogCommand() {
    ajaxResponseRenderer.addCallback(new JavaScriptCallback() {
        @Override
        public void run(JavaScriptSupport javascriptSupport) {
            javascriptSupport.addScript("$('#serviceLineModal').modal('show');");
        }
    });
}

これが誰かの役に立てば幸いです。この投稿は役に立ちました。

于 2014-10-23T15:02:06.943 に答える
1

これは JS の 2 行で簡単です。

var elem = document.getElementById("id");    
alert(elem.getBoundingClientRect());
于 2020-07-18T06:36:51.047 に答える
1

私もこれをそこに投げようと思っただけです。
古いブラウザーでテストすることはできませんでしたが、最新のトップ 3 では動作します。:)

Element.prototype.getOffsetTop = function() {
    return ( this.parentElement )? this.offsetTop + this.parentElement.getOffsetTop(): this.offsetTop;
};
Element.prototype.getOffsetLeft = function() {
    return ( this.parentElement )? this.offsetLeft + this.parentElement.getOffsetLeft(): this.offsetLeft;
};
Element.prototype.getOffset = function() {
    return {'left':this.getOffsetLeft(),'top':this.getOffsetTop()};
};
于 2014-10-12T10:57:36.440 に答える
1

多くの調査とテストの後、これはうまくいくようです

function getPosition(e) {
    var isNotFirefox = (navigator.userAgent.toLowerCase().indexOf('firefox') == -1);
    var x = 0, y = 0;
    while (e) {
        x += e.offsetLeft - e.scrollLeft + (isNotFirefox ? e.clientLeft : 0);
        y += e.offsetTop - e.scrollTop + (isNotFirefox ? e.clientTop : 0);
        e = e.offsetParent;
    }
    return { x: x + window.scrollX, y: y + window.scrollY };
}

http://jsbin.com/xuvovalifo/edit?html,js,outputを参照してください。

于 2015-06-17T20:48:24.567 に答える