检索超文本标记语言元素的位置(X, Y)

我想知道如何获得超文本标记语言元素的X和Y位置,例如JavaScript中的imgdiv

2100809 次浏览

大多数浏览器上的超文本标记语言元素将具有:-

offsetLeftoffsetTop

这些指定元素相对于具有布局的最近父元素的位置。如果offsetP的属性可以访问此父元素。

IE和FF3有

clientLeftclientTop

这些属性不太常见,它们用其父客户端区域指定元素位置(填充区域是客户端区域的一部分,但边框和边距不是)。

使用JavaScript框架可能会更好,该框架具有以独立于浏览器的方式返回此类信息(以及更多!)的函数。以下是一些:

使用这些框架,您可以执行以下操作:$('id-of-img').top获取图像的y像素坐标。

库会竭尽全力获取元素的准确偏移量。
这里有一个简单的函数,在我尝试过的每种情况下都能完成这项工作。

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;

如果使用jQuery,尺寸插件非常好,可以让你准确地指定你想要的。

e. g.

相对位置,绝对位置,绝对位置无填充,带填充…

它还在继续,我们只能说你可以用它做很多事情。

加上使用jQuery的好处是它的轻量级文件大小和易于使用,你不会回到JavaScript没有它之后。

如果page至少包含任何“DIV”,则meouw给出的函数会抛出超出当前页面限制的“Y”值。为了找到确切的位置,您需要同时处理offsetP的和父节点的。

尝试下面给出的代码(检查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];};

jQuery.偏移量将获取第一个元素的当前坐标,或者设置匹配元素集中每个元素相对于文档的坐标。

这是我设法创建的最好的代码(也适用于iframe,不像jQuery的偏移量())。似乎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/safariif ($.browser.webkit) {el = el.parentNode;} else {// firefox/IEel = el.offsetParent;}}return { top: _y, left: _x };}

您可以向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/

正确的方法是使用#0

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

只要您可能关心,Internet Explorer就一直支持它,并且最终在CSSOM视图中标准化。所有其他浏览器都采用了它很久以前

一些浏览器还返回高度和宽度属性,尽管这不是标准的。如果您担心旧浏览器的兼容性,请检查此答案的修订以获得优化的降级实现。

element.getBoundingClientRect()返回的值是相对于视口的。如果你需要它相对于另一个元素,只需从另一个矩形中减去一个矩形:

var bodyRect = document.body.getBoundingClientRect(),elemRect = element.getBoundingClientRect(),offset   = elemRect.top - bodyRect.top;
alert('Element is ' + offset + ' vertical pixels from <body>');

如果你使用jQuery,这可能是一个简单的解决方案:

<script>var el = $("#element");var position = el.position();console.log( "left: " + position.left + ", top: " + position.top );</script>

有效地检索相对于页面的位置,而不使用递归函数:(也包括IE)

var element = document.getElementById('elementId'); //replace elementId with your element's Id.var rect = element.getBoundingClientRect();var elementLeft,elementTop; //x and yvar 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;

我只是想把这个也扔出去。
我还没有能够在旧的浏览器中测试它,但它可以在最新的前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()};};

我成功地使用Andy E的解决方案来定位引导2模式,这取决于用户单击表行中的哪个链接。该页面是Tapestry 5页面,下面的javascript在java页面类中导入。

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() {@Overridepublic void run(JavaScriptSupport javascriptSupport) {javascriptSupport.addScript("$('#serviceLineModal').modal('show');");}});}

希望这能帮助别人,这篇文章帮助了。

我发现最干净的方法是jQueryoffset使用的技术的简化版本。与其他一些答案类似,它从getBoundingClientRect开始;然后使用windowdocumentElement来调整滚动位置以及body上的边距(通常是默认值)。

var rect = el.getBoundingClientRect();var docEl = document.documentElement;
var rectTop = rect.top + window.pageYOffset - docEl.clientTop;var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;

var els = document.getElementsByTagName("div");var docEl = document.documentElement;
for (var i = 0; i < els.length; i++) {
var rect = els[i].getBoundingClientRect();
var rectTop = rect.top + window.pageYOffset - docEl.clientTop;var rectLeft = rect.left + window.pageXOffset - docEl.clientLeft;
els[i].innerHTML = "<b>" + rectLeft + ", " + rectTop + "</b>";}
div {width: 100px;height: 100px;background-color: red;border: 1px solid black;}#rel {position: relative;left: 10px;top: 10px;}#abs {position: absolute;top: 250px;left: 250px;}
<div id="rel"></div><div id="abs"></div><div></div>

由于不同的浏览器以不同的方式呈现边框、填充、边距等。我写了一个小函数来检索你想要的精确维度中每个根元素中特定元素的顶部和左侧位置:

function getTop(root, offset) {var rootRect = root.getBoundingClientRect();var offsetRect = offset.getBoundingClientRect();return offsetRect.top - rootRect.top;}

要检索左位置,您必须返回:

    return offsetRect.left - rootRect.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

我这样做是为了与旧浏览器交叉兼容。

// For really old browser's or incompatible onesfunction getOffsetSum(elem) {var top = 0,left = 0,bottom = 0,right = 0
var width = elem.offsetWidth;var height = elem.offsetHeight;
while (elem) {top += elem.offsetTop;left += elem.offsetLeft;elem = elem.offsetParent;}
right = left + width;bottom = top + height;
return {top: top,left: left,bottom: bottom,right: right,}}
function getOffsetRect(elem) {var box = elem.getBoundingClientRect();
var body = document.body;var docElem = document.documentElement;
var scrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop;var scrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft;
var clientTop = docElem.clientTop;var clientLeft = docElem.clientLeft;

var top = box.top + scrollTop - clientTop;var left = box.left + scrollLeft - clientLeft;var bottom = top + (box.bottom - box.top);var right = left + (box.right - box.left);
return {top: Math.round(top),left: Math.round(left),bottom: Math.round(bottom),right: Math.round(right),}}
function getOffset(elem) {if (elem) {if (elem.getBoundingClientRect) {return getOffsetRect(elem);} else { // old browserreturn getOffsetSum(elem);}} elsereturn null;}

更多关于JavaScript中的坐标:http://javascript.info/tutorial/coordinates

经过大量的研究和测试这似乎工作

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,输出

我采用了@meouw的答案,在允许边框的client左中添加,然后创建了三个版本:

与@meouw类似,这获取相对于文档的body或html元素的绝对位置(取决于quirks模式)

getAbsolteOffsetFromGivenElement-返回相对于给定元素(relativeEl)的绝对位置。请注意,给定元素必须包含元素el,否则其行为将与getAbsolteOffsetFromBody相同。如果您有两个元素包含在另一个(已知)元素中(可选地在节点树中的多个节点中)并希望将它们设置为相同的位置,这很有用。

getAbsolteOffsetFromRelative-返回相对于第一个父元素的绝对位置,其中包含位置:相对。出于相同的原因,这类似于getAbsolteOffsetFromGivenElement,但仅限于第一个匹配元素。

getAbsoluteOffsetFromBody = function( el ){   // finds the offset of el from the body or html elementvar _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 relativeElvar _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: relativevar _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');elsevalString = el.currentStyle['position'];if (valString === "relative")el = null;}}return { top: _y, left: _x };}

如果你仍然有问题,特别是与滚动相关的问题,你可以尝试查看http://www.greywyvern.com/?post=331-我注意到getStyle中至少有一段可疑的代码,假设浏览器表现良好,应该没问题,但根本没有测试其余的代码。

小与小的区别

function getPosition( 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 };}

查看示例坐标:http://javascript.info/tutorial/coordinates

像这样的东西怎么样,通过传递元素的ID,它将返回左侧或顶部,我们也可以组合它们:

1)找到左边

function findLeft(element) {var rec = document.getElementById(element).getBoundingClientRect();return rec.left + window.scrollX;} //call it like findLeft('#header');

2)查找顶部

function findTop(element) {var rec = document.getElementById(element).getBoundingClientRect();return rec.top + window.scrollY;} //call it like findTop('#header');

3)找到左和顶在一起

function findTopLeft(element) {var rec = document.getElementById(element).getBoundingClientRect();return {top: rec.top + window.scrollY, left: rec.left + window.scrollX};} //call it like findTopLeft('#header');

虽然这很可能在这么多答案的底部丢失,但这里的顶级解决方案对我不起作用。
据我所知,其他任何答案都没有帮助。

情况
在HTML5页面中,我有一个菜单,它是标题中的nav元素(不是标题,而是另一个元素中的标题)。一旦用户滚动到导航,我希望导航坚持到顶部,但在此之前,标题是绝对定位的(所以我可以让它稍微覆盖其他东西)。上面的解决方案从未触发过更改,因为. offsetTop不会改变,因为这是一个绝对定位的元素。此外,. scrollTop属性只是最顶层元素的顶部…也就是说0,并且总是0。
我使用这两个(与getBoundingClientRect结果相同)执行的任何测试都不会告诉我导航栏的顶部是否滚动到可查看页面的顶部(再次,正如控制台中报告的那样,它们只是在滚动发生时保持相同的数字)。

解决方案
我的解决方案是使用

window.visualViewport.pageTop

pageTop属性的值反映了屏幕的可视部分,因此允许我跟踪元素在可视区域边界的引用位置。

可能没有必要说,每当我处理滚动时,我都希望使用此解决方案以编程方式响应正在滚动的元素的移动。
希望能帮到别人。
重要提示:这似乎工作在Chrome和Opera目前&绝对不是在Firefox(6-2018)…直到Firefox支持Visual Viewport我建议不要使用这种方法,(我希望他们很快就会这样做……它比其他方法更有意义)。


更新:

虽然我仍然发现我的发现对于“…以编程方式响应滚动元素的移动”的情况非常有价值。对于我遇到的问题,更好的解决方案是使用CSS在元素上设置位置:粘性。使用粘性,你可以在不使用javascript的情况下让元素保持在顶部(注意:有时这不会像将元素更改为固定那样有效,但对于大多数用途,粘性方法可能会更好)

更新01:
所以我意识到,对于不同的页面,我需要在一个稍微复杂的滚动设置中检测元素的位置(视差加上作为消息一部分滚动过去的元素)。在这种情况下,我意识到以下内容提供了我用来确定何时做某事的值:

  let bodyElement = document.getElementsByTagName('body')[0];let elementToTrack = bodyElement.querySelector('.trackme');trackedObjPos = elementToTrack.getBoundingClientRect().top;if(trackedObjPos > 264){bodyElement.style.cssText = '';}

希望这个答案现在更广泛有用。

获取div相对于左和顶的位置

  var elm = $('#div_id');  //get the divvar posY_top = elm.offset().top;  //get the position from topvar posX_left = elm.offset().left; //get the position from left

如果你想只在javascript中完成,这里有一些一个班轮使用#0

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

第一行将返回offsetTop,例如相对于文档的Y。第二行将返回offsetLeft,例如相对于文档的X。

#0是一个javascript函数,它返回元素相对于窗口视口的位置。

要获得元素的总偏移量,您可以递归地总结所有父偏移量:

function getParentOffset(el): number {if (el.offsetParent) {return el.offsetParent.offsetTop + getParentOffset(el.offsetParent);} else {return 0;}}

使用这个效用函数,dom元素的总顶部偏移量为:

el.offsetTop + getParentOffset(el);

更新时间:

递归方法(在我的旧答案中)创建了许多调用堆栈。在这种情况下,我们可以使用年间循环来避免递归:

/**** @param {HTMLElement} el* @return \{\{top: number, left: number}}*/function getDocumentOffsetPosition(el) {let top = 0, left = 0;while (el !== null) {top += el.offsetTop;left += el.offsetLeft;el = el.offsetParent;}return {top, left};}

老答案:

/**** @param {HTMLElement} el* @return \{\{top: number, left: number}}*/function getDocumentOffsetPosition(el) {var position = {top: el.offsetTop,left: el.offsetLeft};if (el.offsetParent) {var parentPosition = getDocumentOffsetPosition(el.offsetParent);position.top += parentPosition.top;position.left += parentPosition.left;}return position;}

感谢的答案,这只是另一个版本。

这就像JS中的两行一样简单:

var elem = document.getElementById("id");alert(elem.getBoundingClientRect());

    
HTML program to show (x, y) of anelement by dragging mouse over it  you just copied it and use it on your own<!DOCTYPE html><html><head><title>position of an element</title>        
<!-- scropt to get position --><script type = "text/javascript">function getPositionXY(element) {var rect = element.getBoundingClientRect();document.getElementById('text').innerHTML= 'X: ' + rect.x + '<br>' + 'Y: ' + rect.y;}</script></head>    
<body><p>Move the mouse over the text</p>        
<div onmouseover = "getPositionXY(this)">Position:<p id = 'text'></p></div>    
</body></html>                 

这是一个使用vanilla JS递归迭代#0#1的现代1-line:

功能:

getTop = el => el.offsetTop + (el.offsetParent && getTop(el.offsetParent))

用法:

const el = document.querySelector('#div_id');const elTop = getTop(el)

优势:

无论当前滚动位置如何,始终返回绝对垂直偏移量。


传统语法:

function getTop(el) {return el.offsetTop + (el.offsetParent && getTop(el.offsetParent));}

我可以只喜欢element.offsetLeftelement.offsetTop。示例:document.getElementById('profileImg').offsetLeft