JavaScriptのimg
やなどの HTML 要素の X と Y の位置を取得する方法を知りたいです。div
29 に答える
正しいアプローチは、次を使用すること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>');
ライブラリは、要素の正確なオフセットを取得するためにある程度の時間を費やします。
これは、私が試したすべての状況で機能する単純な関数です。
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;
この関数は、ドキュメント (ページ) 全体に対する要素の位置を返します。
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
javascript のみで実行したい場合は、次のライナー を使用しますgetBoundingClientRect()
window.scrollY + document.querySelector('#elementId').getBoundingClientRect().top // Y
window.scrollX + document.querySelector('#elementId').getBoundingClientRect().left // X
offsetTop
最初の行は、ドキュメントに相対的な Yを返します。offsetLeft
2 行目は、ドキュメントに相対的な Xを返します。
getBoundingClientRect()
ウィンドウのビューポートに対する要素の位置を返す JavaScript 関数です。
ほとんどのブラウザの HTML 要素には次のものがあります:-
offsetLeft
offsetTop
これらは、レイアウトを持つ最も近い親に対する要素の位置を指定します。多くの場合、この親は、offsetParent プロパティを介してアクセスできます。
IEとFF3は
clientLeft
clientTop
これらのプロパティはあまり一般的ではなく、親のクライアント領域で要素の位置を指定します (パディング領域はクライアント領域の一部ですが、ボーダーとマージンはそうではありません)。
ページに少なくとも「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];
};
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/
再帰関数を使用せずに、ページに対する相対的な位置を効率的に取得するには: (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;
jQuery .offset()は、ドキュメントを基準にして、最初の要素の現在の座標を取得するか、一致した要素のセット内のすべての要素の座標を設定します。
私は@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 つあることに気付きました。 、しかし残りはまったくテストしていません。
jQuery を使用している場合、ディメンション プラグインは優れており、必要なものを正確に指定できます。
例えば
相対位置、絶対位置、パディングなしの絶対位置、パディングあり...
それは続きます、それでできることはたくさんあるとだけ言っておきましょう。
さらに、jQuery を使用する利点は、ファイル サイズが軽量で使いやすいことです。後で jQuery なしでは JavaScript に戻れません。
これは私が作成した中で最高のコードです (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 };
}
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');");
}
});
}
これが誰かの役に立てば幸いです。この投稿は役に立ちました。
これは JS の 2 行で簡単です。
var elem = document.getElementById("id");
alert(elem.getBoundingClientRect());
私もこれをそこに投げようと思っただけです。
古いブラウザーでテストすることはできませんでしたが、最新のトップ 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()};
};
多くの調査とテストの後、これはうまくいくようです
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 };
}