一、大多数JavaScript方法处理的是以下两种坐标系中的一个
1、相对于窗口:类似于position:fixed,从窗口的顶部/左侧边缘计算得出。
(1)我们将这些坐标表示为clientX/clientY
2、相对于文档:与文档根(document root)中的position:absolute类似,从文档的顶部/左侧边缘计算得出
(1)我们将它们表示为pageX/pageY
二、当页面滚动到最开始时,此时窗口的左上角恰好是文档的左上角,它们的坐标彼此相等。但是,在文档移动之后,元素的窗口相对坐标会发生变化,因为元素在窗口移动,而元素在文档中的相对坐标保持不变。
image.png

元素坐标:getBoundingClientRect

一、方法elem.getBoundingClientRect()返回最小矩形的窗口坐标,该矩形将elem作为内建DOMRect类的对象。
1、主要的DOMRect属性
(1)x/ y:矩形原点相对于窗口的X/Y坐标。
(2)width / height:矩形的width / height(可以为负)
2、派生(derived)属性
(1)top/ bottom:顶部/底部矩形边缘的Y坐标。
① top = y
② bottom = y + height
(2)left/ right:左/右矩形边缘的X坐标。
① left = x
② right = x + width
image.png
二、坐标可能是小数,例如10.5。这是正常的,浏览器内部使用小数进行计算。在设置style.left/top时,不必对它们进行舍入。
三、坐标可能是负数。例如滚动页面,使elem现在位于窗口的上方,则elem.getBoundingClientRect().top为负数。
四、IE浏览器不支持x/y属性
1、我们可以写一个polyfill(在DomRect.prototype中添加一个getter),或者仅使用top、left,因为对于正值的width/ height来说,它们和x/ y一直是一样的,尤其是对于elem.getBoundingClientRect()的结果。
五、坐标的right/ bottom与CSS position属性不同
1、相对于窗口(window)的坐标和CSS position:fixed之间有明显的相似之处。
2、在CSS定位中,right属性表示距右边缘的距离,而bottom属性表示距下边缘的距离。
3、在JavaScript并非如此。窗口的所有坐标都从左上角开始计数,包括这些坐标。

elementFromPoint(x, y)

一、对document.elementFromPoint(x, y)的调用会返回在窗口坐标(x, y)处嵌套最多(the most nested)的元素
二、语法

  1. let elem = document.elementFromPoint(x, y);

【示例1】高亮显示并输出现在位于窗口中间的元素的标签

let centerX = document.documentElement.clientWidth / 2;
let centerY = document.documentElement.clientHeight / 2;
let elem = document.elementFromPoint(centerX, centerY);
elem.style.background = 'red';
alert(elem.tagName);

1、因为它使用的是窗口坐标,所以元素可能会因当前滚动位置而有所不同。
2、对于在窗口之外的坐标,elementFromPoint返回null
(1)方法document.elementFromPoint(x, y)只对在可见区域内的坐标(x, y)起作用。
(2)如果任何坐标为负或者超过了窗口的width/ height,那么该方法就会返回null
(3)如果我们没有对其进行检查,可能就会发生如下典型错误:

let elem = document.elementFromPoint(x, y);
// 如果坐标恰好在窗口外,则elem = null
elem.style.background = ''; // Error

文档坐标

一、文档相对坐标从文档的左上角开始计算,而不是窗口。
二、在CSS中,窗口坐标对应于position: fixed,而文档坐标与顶部的position: absolute类似。
三、我们可以使用position: absolute和top/ left来把某些内容放到文档中的某个位置,以便在页面滚动时,元素仍能保留在该位置,但是我们首先需要正确的坐标。
四、pageX, pageY可以通过以下公式相连接
1、pageY = clientY + 文档的垂直滚动出的部分的高度
2、pageX = clientX + 文档的水平滚动出的部分的宽度
【示例1】getCoords(elem)将从elem.getBoundingClientRect()获取窗口坐标,并向其中添加当前滚动

// 获取元素的文档坐标
function getCoords(elem) {
    let box = elem.getBoundingClientRect();

    return {
        top: box.top + window.pageYOffset,
        right: box.right + widow.pageYOffset,
        bottom: box.bottom + window.pageYOffset,
        left: box.left + widow.pageXOffset
    }
}