使用内联offsetparent获取元素左/顶部的实际偏移量

时间:2011-03-28 13:46:29

标签: jquery html css dom offset

我正在尝试获取页面上元素的坐标。我一直在使用标准方法来获取它:

var el = element, pos = {x: 0, y: 0};
while ( el ) {
    pos.x += el.offsetLeft;
    pos.y += el.offsetTop;
    el = el.offsetParent;
}

但是当有问题的元素有display: block时,此方法失败,而其中一个offsetParents有display: inline;。这是由于this thread

中描述的事实

The element starts in the middle of the text

在尝试使用jQuery之后,事实证明他们的.offset() - 方法返回了正确的偏移量,并且我查看了源代码,但没有找到他们是如何做到的。所以我的问题是:我如何获得确切的位置?我不能在这个项目中使用jQuery,the thread described earlier中的方法很麻烦,添加元素和测试工作太多(性能视角),并且使用Element.getBoundingClientRect也不可用。< / p>

如果您想尝试一下,可以转到Apple.com打开您选择的调试器并输入以下内容:

var el, el2;
el = el2 = document.querySelector('#worldwide span');
var pos = {x: 0, y: 0};
while ( el2 ) {
    pos.x += el2.offsetLeft;
    pos.y += el2.offsetTop;
    el2 = el2.offsetParent;
}
alert("Calculated position: " + pos.x + "x" + pos.y + " window size: " + screen.width + "x" + screen.height);

使用这段代码我得到:Calculated position: 1354x988 window size: 1280x800(即左边的偏移是屏幕的方式,显然不是这样)

这怎么可能?任何解决方法的想法?约稿?它不一定非常精确,但必须比以前更好。感谢。

编辑:这是为WebKit渲染引擎澄清的。

4 个答案:

答案 0 :(得分:2)

我最终选择了WebKit的window.webkitConvertPointFromNodeToPage,但是我一直遇到一个错误,它会返回一个完全错误的位置。进一步的调查显示,如果有问题的节点显示为:inline,那么它将返回层次结构中最后一个块元素的位置。

搜索这个图像的分辨率没有任何结果(我发现的只是关于webkitConvertPointFromNodeToPage实际做了什么和WebKit的源代码的非常基本的信息)。

猜测我发现如果元素有display: inline-block,它返回了正确的位置,所以如果元素是内联的,那么我将它改为内联块,然后计算位置。

如果有人对此问题有更好的解决方案,我很乐意听取您的意见!

修改

原来改变显示样式到内联块并不总是一个好主意,所以我没有这样做,而是使用这种方法:

var offset = {x: 0, y: 0};
if ( getStyle(el, 'display') == 'inline' ) {
    offset.x = el.offsetLeft - el.parentNode.offsetLeft;
    offset.y = el.offsetTop - el.parentNode.offsetTop;
}

var point = window.webkitConvertPointFromNodeToPage(el, new WebKitPoint(0, 0));

return {
    x: Math.round(point.x + offset.x),
    y: Math.round(point.y + offset.y)
}

我正在使用内联子项的offsetTop / Left并从它的父项中减去它。我不确定它如何适用于有显示内容的父母:内联,但它在90%的时间都有效。

但如果有人有更好的想法,我仍然愿意接受建议。

答案 1 :(得分:1)

可能here您会找到the source code of jQuery.offset中使用的提示的说明。

如果你看here,你可以看到offsetLeftoffsetTop在旧的IE版本中工作不正确。

我理解理解如何实现这些或其他事情很有意思。如何看待jQuery.offset函数的源代码并不那么容易。如果您希望代码正常工作并且与浏览器无关,那么最好使用jQuery.offset而不是编写自己的实现。

答案 2 :(得分:1)

对webkitConvertPointFromNodeToPage源代码的检查显示它使用元素渲染器对象计算,如果不存在这样的渲染器,则它使用具有渲染器的neareset祖先。但是,当使用祖先渲染器时,它不会调整偏移量来解释目标与其祖先原点之间的原点差异。这意味着当相对于包含渲染器给出该点时,该函数可以正常工作。如果您计算坐标的元素没有渲染器,则需要手动将偏移调整到最近的祖先(使用offsetLeft / Top)。要准确了解哪些元素具有渲染器需要更多研究,但通常任何没有内容但影响其他节点显示的元素(如SPAN)都不需要渲染器。

答案 3 :(得分:1)

在jQuery中使用$.offset().left时遇到了同样的问题,试图获取段落中单词的位置。

$.offset().left函数中使用$(document).ready()会产生错误的结果。

$.offset().left函数中使用$(window).load()解决了我在WebKit中的问题。

在可能存在影响布局的浮动图像元素或字体的情况下,这尤其重要。