简体   繁体   English

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

[英]JavaScript getBoundingClientRect() changes while scrolling

I want to have the exact distance between the Y-coordinate of an element an the Y-value=0, which I consider as the top of the document. 我想要一个元素的Y坐标和Y值= 0之间的确切距离,我认为它是文档的顶部。

myElement.getBoundingClientRect().top;

But the value of getBoundingClientRect() seems to change while scrolling. 但是getBoundingClientRect()的值似乎在滚动时发生了变化。 How can I get the real distance between myElement and the Y-coordinate=0 (top of document)? 如何获得myElement和Y坐标= 0(文档顶部)之间的实际距离?

It is because getBoundingClientRect() gets values with respect to the window (only the current visible portion of the page), not the document (whole page). 这是因为getBoundingClientRect()获取相对于window值(仅页面的当前可见部分),而不是document (整个页面)。
Hence, it also takes scrolling into account when calculating its values 因此,在计算其值时也需要考虑滚动
Basically, document = window + scroll 基本上, document = window + scroll

So, to get the distance between myElement and the Y-coordinate=0 (top of document), you would have add the value of vertical-scroll also: 因此,要获得myElement和Y坐标= 0(文档顶部)之间的距离,您还可以添加垂直滚动的值:

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

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

getBoundingClientRect needs a bit more care to avoid bugs in scrollY/pageYOffset: 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
    };
}

The bugs to avoid are: 要避免的错误是:

  • scrolling in Android Chrome since Chrome Mobile 43 has wrong values for scrollY/pageYOffset (especially when the keyboard is showing and you scroll). 在Android Chrome中滚动,因为Chrome Mobile 43的scrollY / pageYOffset 不正确(特别是当键盘显示并滚动时)。

  • Pinch-zoom in Microsoft IE or Edge causes wrong values for scrollY/pageYOffset. 在Microsoft IE或Edge中进行缩放会导致scrollY / pageYOffset的不正确。

  • Some (obsolete) browsers don't have a height/width eg IE8 一些(过时的)浏览器没有高度/宽度,例如IE8

Edit: The above code can be simplified a lot by just using document.body.getBoundingClientRect() instead of adding a div - I haven't tried it though so I am leaving my answer as it stands. 编辑:上面的代码可以简单地通过使用document.body.getBoundingClientRect()而不是添加div来简化 - 我没有尝试过,所以我现在就离开我的答案了。 Also the body needs margin:0 (reset.css usually does this). 身体也需要margin:0 (reset.css通常这样做)。 This answer simplifies the code down a lot, while still avoiding the bugs in jQuery.offset()! 这个答案简化了代码,同时仍然避免了jQuery.offset()中的错误!

Edit 2: Chrome 61 introduced window.visualViewport to give correct values for the actual viewport which is probably another way to fix issues; 编辑2: Chrome 61引入了window.visualViewport ,为实际视口提供了正确的值,这可能是解决问题的另一种方法; but beware that Android Chrome 66 was still buggy if Settings -> Accessability -> Force enable zoom was ticked (bugs with orientation change, focused inputs, absolutely positioned popup wider than viewport). 但请注意,如果Settings -> Accessability -> Force enable zoom ,则Android Chrome 66仍然存在错误(方向更改错误,聚焦输入,绝对定位的弹出窗口比视口更宽)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM