如何在Javascript中获取页面上对象的绝对位置?

112

我想在 Javascript 中获取一个对象在页面上的绝对 x,y 位置。该如何实现?

我尝试使用 obj.offsetTopobj.offsetLeft,但它们仅提供相对于父元素的位置。 我猜我可以循环遍历并添加父元素的偏移量,以及其父元素的偏移量,直到找到没有父元素的对象,但这似乎不是最好的方法。 搜寻 Google 没有发现什么有用的结果,即使在 SO 网站搜索也没有找到任何信息。

另外,我不能使用 jQuery。


3
动态检索HTML元素的X Y位置与JavaScript - Crescent Fresh
2
另一个重复问题:https://dev59.com/EnVC5IYBdhLWcg3w21Mq - Crescent Fresh
网站搜索又失败了!谢谢大家,我想这肯定以前出现过。 - Kip
1
点赞!因为提出了一个真正(没有框架)的JavaScript问题。@Sk8erPeter的答案是正确的。 - John
2个回答

198
var cumulativeOffset = function(element) {
    var top = 0, left = 0;
    do {
        top += element.offsetTop  || 0;
        left += element.offsetLeft || 0;
        element = element.offsetParent;
    } while(element);

    return {
        top: top,
        left: left
    };
};

(方法无耻地从PrototypeJS偷取;代码风格,变量名称和返回值已更改以保护无辜者)


29
我喜欢在代码下方留言 :D - Lukas Liesis
3
谢谢!我只能给一个赞 :) - Akash
3
注意,这个元素必须使用相对定位、绝对定位或固定定位进行样式设置,我想是这样的吧? - codenoob
太喜欢这个评论了!:) - mjquito
不是最有效率的方法,我认为这只是一种hack。Sk8erPeter的回答更加恰当。 - yago

161

我建议使用element.getBoundingClientRect()

https://developer.mozilla.org/zh-CN/docs/Web/API/element.getBoundingClientRect

摘要

返回一个文本矩形对象,该对象包含一组文本矩形。

语法

var rectObject = object.getBoundingClientRect();

返回值

返回的值是一个TextRectangle对象,它是元素的getClientRects()返回的矩形的并集,即与元素相关联的CSS边框框盒。

返回的值是一个TextRectangle对象,其中包含只读属性lefttoprightbottom,描述相对于视口左上角的边框框盒的位置和尺寸(以像素为单位)。

以下是从链接的MDN网站中提取的浏览器兼容性表:

+---------------+--------+-----------------+-------------------+-------+--------+
|    Feature    | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
+---------------+--------+-----------------+-------------------+-------+--------+
| Basic support | 1.0    | 3.0 (1.9)       | 4.0               | (Yes) | 4.0    |
+---------------+--------+-----------------+-------------------+-------+--------+

它得到了广泛的支持,而且非常容易使用,更不用说它速度超快。以下是John Resig的相关文章:http://ejohn.org/blog/getboundingclientrect-is-awesome/

您可以像这样使用:

var logo = document.getElementById('hlogo');
var logoTextRectangle = logo.getBoundingClientRect();

console.log("logo's left pos.:", logoTextRectangle.left);
console.log("logo's right pos.:", logoTextRectangle.right);

这里有一个非常简单的示例: http://jsbin.com/awisom/2 (您可以通过点击右上角的"在JS Bin中编辑"来查看和编辑代码)。

或者,这里是另一个使用Chrome控制台的例子:Using element.getBoundingClientRect() in Chrome

注意:

我必须提到,在Internet Explorer 8中,getBoundingClientRect()方法返回值的widthheight属性为undefined。但它在Chrome 26.x、Firefox 20.x和Opera 12.x中都有效。在IE8中的解决方法:对于width,您可以减去返回值的right和left属性,对于height,您可以减去bottom和top属性(像这样)。


73
这是完全不同的用例吗?滚动页面并再次检查您的值...getBoundingClientRect()是相对于滚动窗口的位置...当您滚动过标志时,您的顶部值将变为负数。 - jondavidjohn
19
@jondavidjohn 当然,但可以通过添加 window.pageYOffset(或者如果你真的需要 IE8 兼容性,(window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop)轻松调整。水平滚动也是一样。 - user123444555621
24
我认为你应该编辑答案,以包含这个页面偏移片段,并以回答原始OP的问题。成为最受欢迎的答案需要承担一些责任;) - etov
5
在我的情况下,getBoundingClientRect 返回了错误的顶部偏移量。@eyelidlessness 的建议是有效的。 - AntonAL
10
但是,getBoundingClientRect 不返回元素的 xy 绝对位置。 - Mike Czarnota
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接