【问题标题】:Get real offset left/top of element with inline offsetparent使用内联 offsetparent 获取元素的真实偏移左/顶部
【发布时间】:2011-07-24 12:17:47
【问题描述】:

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

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中描述的事实:

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

如果您想尝试一下,可以转到 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 渲染引擎澄清的。

【问题讨论】:

    标签: jquery html css dom offset


    【解决方案1】:

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

    搜索这张图片的分辨率一无所获(我发现的只是关于 webkitConvertPointFromNodeToPage 实际做了什么以及 WebKit 源代码的非常基本的信息)。

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

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

    编辑:

    事实证明,将显示样式更改为 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 并从它的父项中减去它。我不太确定它在具有 display: inline 的父母身上是如何工作的,但它在 90% 的时间里都有效。

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

    【讨论】:

      【解决方案2】:

      可能here你会发现the source code of jQuery.offset中使用的想法的描述。

      如果您查看here,您会发现offsetLeftoffsetTop 在旧版IE 中的工作方式并不完全正确。

      我知道了解如何实现此功能或其他功能很有趣。你怎么看jQuery.offset函数的源代码不是那么容易的。如果您希望您的代码正确运行并且独立于浏览器,您最好只使用jQuery.offset 而不是编写自己的实现。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-02-02
            • 2021-05-08
            • 2021-11-20
            • 1970-01-01
            • 2015-03-26
            • 1970-01-01
            • 2021-03-15
            相关资源
            最近更新 更多