坐标

306 阅读3分钟

当移动页面的元素时,会经常使用到坐标。

一般来说,有两种坐标系。

  • 相对于视口(窗口)顶部/左侧计算的坐标
  • 相对于文档顶部/左侧计算的坐标

窗口坐标:getBoundingClientRect

Element.getBoundingClientRect()方法返回一个对象包含元素的大小及其相对于视口的位置。

该对象包含了一组用于描述边框的只读属性——left、top、right和bottom。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。如下图所示:

窗口坐标并不会考虑到文档滚动,它们就是基于窗口的左上角计算出来的。

换句话说,当我们滚动这个页面,这个元素就会上升或者下降,它的窗口坐标也会随之改变

注意: 相对窗口的坐标和 CSS 中的 position:fixed 有明显的相似之处 — 也是相对于视口的位置。

文档坐标

文档相对坐标是从文档的左上角开始计算,而不是窗口。

在 CSS 中,窗口坐标对应的是 position:fixed,而文档坐标则类似顶部的 position:absolute。

为了清楚起见我们把窗口坐标叫做 (clientX,clientY) 把文档坐标叫做 (pageX,pageY)。

当页面没有滚动时,窗口坐标和页面坐标实际上是相同的,它们的零点也匹配:

当我们滚动页面,那么 (clientX,clientY) 就会改变,因为它们是相对于窗口计算的,但是 (pageX,pageY) 不会变。

这里是垂直滚动后的同一页面:

  • 包含 "From today's featured article" 的 header 元素 clientY 变成 0,因为这个元素现在在窗口的顶部。
  • clientX 并没有改变,因为没有水平滚动。
  • 元素的 pageX 和 pageY 坐标始终保持一致,因为它们是相对于文档计算的。

获取文档坐标

要获取元素相对于文档坐标很简单,尽管没有标准方法。

由于 getBoundingClientRect 方法可以获取元素相对于窗口的位置,当元素向上或向下移动时 ,窗口的位置会发生变化,而文档坐标指的是元素在文档中相对文档左上角的位置,当页面发生滚动时,只需要把滚出去的那个距离加上元素相对于窗口的位置即可。

  • pageY = clientY + 文档垂直部分滚动的高度。
  • pageX = clientX + 文档水平部分滚动的宽度。

而文档垂直部分与水平部分滚动的距离可以使用 window.pageYOffset、window.pageXOffset 获取。

函数 getElementCoords(elem) 将从 element.getBoundingClientRect() 获取到窗口坐标然后加上当前滚动的长度:

//获取元素的文档坐标
function getElementCoords(element) {
  let box = element.getBoundingClientRect()
  return {
    top: box.top + pageYOffset,
    left: box.left + pageXOffset
  }
}

总结

  1. 元素相对于窗口的坐标 —— 用 element.getBoundingClientRect()获取。
  2. 元素相对于文档的坐标 — 用elem.getBoundingClientRect() 加上当前页面滚动的长度获取。
  3. 窗口坐标非常适合和 position:fixed 一起使用,文档坐标非常适合和 position:absolute 一起使用。