滚动时 JavaScriptgetBoundingClientRect()发生更改

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

myElement.getBoundingClientRect().top;

但是,当滚动时,getbound ingClientRect ()的值似乎会发生变化。如何得到 myElement 和 Y 坐标 = 0(文档顶部)之间的实际距离?

99954 次浏览

这是因为 getBoundingClientRect()获取的值与 window(只是页面的当前可见部分)有关,而与 document(整个页面)无关。
因此,在计算它的值时,它也考虑了滚动
基本上,document = window + scroll < br >

因此,要得到 myElement 和 Y 坐标 = 0(文档顶部)之间的距离,还需要添加竖向滚动的值:

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

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

为了避免 scrollY/pageYOffset 中的错误,getbound ingClientRect 需要多加小心:

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
};
}

要避免的错误有:

  • 在安卓浏览器中滚动,因为 Chrome Mobile 43有 错误的价值观用于 scrollY/pageYOffset (特别是当显示键盘并滚动时)。

  • 在 MicrosoftIE 或 Edge 中缩放会导致对 scrollY/pageYOffset 使用 错误的价值观

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

编辑: 上面的代码可以通过使用 document.body.getBoundingClientRect()而不是添加 div 来简化很多——我还没有试过,所以我把我的答案保留下来。主体也需要 margin:0(reset.css 通常这样做)。这个答案极大地简化了代码,同时仍然避免了 jQuery.offet ()中的 bug!

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