滚动时JavaScript getBoundingClientRect()会发生变化

enz*_*ian 57 javascript getboundingclientrect

我想要一个元素的Y坐标和Y值= 0之间的确切距离,我认为它是文档的顶部.

myElement.getBoundingClientRect().top;
Run Code Online (Sandbox Code Playgroud)

但是getBoundingClientRect()的值似乎在滚动时发生了变化.如何获得myElement和Y坐标= 0(文档顶部)之间的实际距离?

n4m*_*d3r 86

这是因为getBoundingClientRect()获取相对于window(仅页面的当前可见部分)的值,而不是document(整个页面).
因此,在计算其值时也需要考虑滚动
基本上, document = window + scroll

因此,要获得myElement和Y坐标= 0(文档顶部)之间的距离,您还可以添加垂直滚动的值:

myElement.getBoundingClientRect().top + window.scrollY;

资料来源:https://developer.mozilla.org/en-US/docs/Web/API/Element.getBoundingClientRect

  • 对于Android Chrome 43,您的解决方案已被破解,如果在Internet Explorer上使用缩放缩放,我认为这已经破解了(我的修复程序是很久以前用来修复问题的.) (2认同)

rob*_*cat 29

getBoundingClientRect需要更多关注以避免scrollY/pageYOffset中的错误:

function absolutePosition(el) {
    var
        found,
        left = 0,
        top = 0,
        width = 0,
        height = 0,
        offsetBase = absolutePosition.offsetBase;
    if (!offsetBase && document.body) {
        offsetBase = absolutePosition.offsetBase = document.createElement('div');
        offsetBase.style.cssText = 'position:absolute;left:0;top:0';
        document.body.appendChild(offsetBase);
    }
    if (el && el.ownerDocument === document && 'getBoundingClientRect' in el && offsetBase) {
        var boundingRect = el.getBoundingClientRect();
        var baseRect = offsetBase.getBoundingClientRect();
        found = true;
        left = boundingRect.left - baseRect.left;
        top = boundingRect.top - baseRect.top;
        width = boundingRect.right - boundingRect.left;
        height = boundingRect.bottom - boundingRect.top;
    }
    return {
        found: found,
        left: left,
        top: top,
        width: width,
        height: height,
        right: left + width,
        bottom: top + height
    };
}
Run Code Online (Sandbox Code Playgroud)

要避免的错误是:

  • 在Android Chrome中滚动,因为Chrome Mobile 43 的scrollY/pageYOffset 不正确(特别是当键盘显示并滚动时).

  • 在Microsoft IE或Edge中进行缩放会导致scrollY/pageYOffset的不正确.

  • 一些(过时的)浏览器没有高度/宽度,例如IE8

编辑:上面的代码可以通过使用document.body.getBoundingClientRect()而不是添加div 来简化很多- 虽然我没有尝试过,所以我现在留下我的答案.身体也需要margin:0(reset.css通常这样做).这个答案简化了代码,同时仍然避免了jQuery.offset()中的错误!

编辑2:引入Chrome 61window.visualViewport以提供实际视口的正确值,这可能是解决问题的另一种方法; 但要注意Android Chrome 66仍然存在错误(如果Settings -> Accessability -> Force enable zoom被勾选)(方向改变的错误,聚焦输入,绝对定位的弹出窗口比视口更宽).