当移动页面的元素时,会经常使用到坐标。
一般来说,有两种坐标系。
- 相对于视口(窗口)顶部/左侧计算的坐标
- 相对于文档顶部/左侧计算的坐标
窗口坐标: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
}
}
总结
- 元素相对于窗口的坐标 —— 用
element.getBoundingClientRect()
获取。 - 元素相对于文档的坐标 — 用
elem.getBoundingClientRect()
加上当前页面滚动的长度获取。 - 窗口坐标非常适合和 position:fixed 一起使用,文档坐标非常适合和 position:absolute 一起使用。