获取元素相对于溢出页面的位置

Yas*_*ouh 3 html javascript dom

我想获取某个元素相对于整个页面的位置,但该元素位于可滚动容器中,这使得通常使用的方法无用。(谈论getBoundingClientRect()offsetTop等等)

作为我的意思的一个例子: https ://material.angular.io/cdk/drag-drop/overview

在“基本拖放”部分中,如果您在不滚动页面的情况下获取元素的 Y 位置,则会得到 626element.getBoundingClientRect().top

滚动之前

现在,如果向下滚动,使该元素几乎接触到窗口顶部,则对于相同的完全相同的元素,您会得到 70

滚动后

但我想要的是相对于整个页面完全相同的值,因此滚动后该值不应该改变。我知道默认滚动行为就是这种情况,但在这种情况下,主体不会滚动,但它的元素会滚动。

Wai*_*mal 5

如果您可以识别元素所在的可滚动容器,则可以简单地将其垂直滚动偏移量 ( scrollTop) 添加到 的结果中getBoundingClientRect().top

另一方面,如果您不知道元素的父树中的哪个容器是可滚动的,或者您的元素有多个可滚动父元素,则可以检查元素的树直至顶部节点,即元素,<html>document.documentElement

function getPageOffset(elem) {
  let topOffset = elem.getBoundingClientRect().top;

  while (elem != document.documentElement) {
    elem = elem.parentElement;
    topOffset += elem.scrollTop;
  }
  return topOffset;
}
Run Code Online (Sandbox Code Playgroud)

下面是一个嵌套在三个可滚动容器树中的段落的简单示例,它利用了上述函数(您可能需要调整浏览器视口的大小才能显示滚动条):

function getPageOffset(elem) {
  let topOffset = elem.getBoundingClientRect().top;

  while (elem != document.documentElement) {
    elem = elem.parentElement;
    topOffset += elem.scrollTop;
  }
  return topOffset;
}
Run Code Online (Sandbox Code Playgroud)
var myElem = document.getElementById("myElem");

function getPageOffset(elem) {
  let topOffset = elem.getBoundingClientRect().top;

  while (elem != document.documentElement) {
    elem = elem.parentElement;
    topOffset += elem.scrollTop;
  }
  return topOffset;
}

document.getElementById("myBtn").addEventListener("click", function() {
  console.log(getPageOffset(myElem));
});
Run Code Online (Sandbox Code Playgroud)
.parent1,
.parent2,
.parent3 {
  height: 100vh;
  overflow-y: auto;
}

.parent1 {
  height: 400px;
}

button {
  position: fixed;
  top:  20px;
  left: 20px;
}
Run Code Online (Sandbox Code Playgroud)

测量之间的误差幅度可以忽略不计(由于附加误差),可以通过某种舍入来克服。