JavaScript | 点击事件对象常用坐标属性

在JavaScript中,存在着事件对象,事件对象回记录事件触发时候的相关信息,比如鼠标点击事件就会记录鼠标点击时候的的位置相关信息,而这里又存在着几个个比较常用的坐标属性,它们是offsetX/offsetYpageX/pageYlayerX/layerYscreenX/screenY以及clientX/clientY,现在就来简单介绍一下这几个属性吧。

offsetX/offsetY、pageX/pageY以及clientX/clientY

先康康MDN官网对这几个属性的定义

  • offsetX/offsetY:MouseEvent 接口的只读属性 offsetX/offsetY 规定了事件对象与目标节点的内填充边(padding edge)在 X/Y 轴方向上的偏移量。——(MDN-MouseEvent.offsetX
  • pageX/pageYpageX/pageY 是一个由MouseEvent接口返回的相对于整个文档的x/y坐标以像素为单位的只读属性。——(MDN-MouseEvent.pageX
  • clientX/clientY:MouseEvent.clientX/MouseEvent.clientY 是只读属性, 它提供事件发生时的应用客户端区域的水平/垂直坐标 (与页面坐标不同)。——(MDN-MouseEvent.clientX

简单整理了一下可以这样理解

  • offsetX/offsetY:返回的是点击时候相对点击的元素左上角的相对位置(包含外边距)的坐标
  • pageX/pageY:返回的是整个文档的坐标,如果此时页面比较长可以获取文档中鼠标的坐标
  • clientX/clientY:返回的是鼠标点击的时候光标浏览器可视范围相对左上角的坐标

下面就来验证一下:

首先准备这样一个页面

CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
body {
  height: 3000px;
}

.test {
  width: 150px;
  height: 150px;
  background-color: aquamarine;
  border: 10px solid black;
}

HTML:

1
<div class="test"></div>

现在页面上看起来是这样的

截图

document对象添加一个点击事件

1
2
3
4
5
document.addEventListener('click',function(e) {
  console.log('clientX:' + e.clientX, 'clientY:' + e.clientY);
  console.log('offsetX:' + e.offsetX, 'offsetY' + e.offsetY);
  console.log('pageX:' + e.pageX, 'offsetY' + e.pageY);
});

现在点击页面上的这里

截图

输出:

  • clientX:18 clientY:18
  • offsetX:0 offsetY:0
  • pageX:18 pageY:18

可以看到当点击此处的时候,因为点击的是test盒子左上角的原点,所以offsetXoffsetY输出的是点击时候相对点击的元素左上角的相对位置(注:test盒子自身有内边距(padding),offsetX和offsetY都是将内边距包含在内的),所以均输出0

clientX/clientYpageX/pageY输出的均为18px,这里可以通过之前设置的css进行计算

首先body元素本身就有外边距(margin),外边距(margin)的值为8px,如下图

截图

而test盒子本身的边框为10px,此时点击test盒子自身的左上角,对应的clientX/clientY以及pageX/pageY输出的值就是8+10=18px验证成功!

但是此时还没看出这两个属性的区别,现在再准备一个测试用的div盒子,对应的CSS和HTML如下:

CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#absolute {
  width: 150px;
  height: 150px;
  background-color: pink;
  padding: 20px;
  border: 10px solid black;
  position: absolute;
  top: 1500px;
  left: 500px;
}

HTML:

1
<div id="absolute"></div>

现在页面如大致结构下图所示:

截图

现在点击id为absolute的盒子的边宽的左上角

截图

此时输出的值为:

  • clientX:500 clientY:300
  • offsetX:-10 offsetY:-10
  • pageX:500 pageY:1500

pageX/pageY的值是如何得到的:

此时用绝对定位将元素定位在top: 1500px left: 500px的位置上,pageX/pageY返回的是整个文档的坐标,pageX/pageY对应的值也是500/1500

clientX/clientY的值是如何得到的:

clientX/clientY返回的是浏览器可视窗口的坐标,在水平距离上clientX的返回值与pageX一致,而垂直距离可以使用像素的距离计算出来

首先用截图软件看下此时id为absolute的元素左上角的坐标

截图

然后看下浏览器可视窗口上边界的坐标

截图

将Y轴上的坐标做个相减461-161=300,验证成功,clientX/clientY以及pageX/pageY的结果均符合预期。

如果对上面说的有不理解的地方可以参考下面这张图:

截图

至于此时的offsetX/offsetY的值均为-10是因为offsetX/offsetY只计算包含到内边距(padding)的距离而边框(border)在内边距之外,所以返回的自然就是负数了,而此元素的边框(border)又为10px,所以返回的值就是-10了。

screenX/screenY

screenX/screenY 是只读属性,他提供了鼠标相对于屏幕坐标系的水平偏移量。——(MDN-MouseEvent.screenX

可以简单理解为下面这句话:

  • screenX/screenY返回的是鼠标点击的时候光标相对屏幕左上角的坐标

验证:

准备下面一段js代码

1
2
3
document.addEventListener('click',function(e) {
  console.log('screenX:'+e.screenX, 'screenY:' + e.screenY);
});

现在在页面上点击任意一点

输出:

  • screenX:521 screenY:401

这个时候打开截图工具查看下鼠标光标对应的坐标

截图

可以看到与js代码输出的结果是完全一致的。

layerX/layerY

首先看下MDN官方对于此属性的定义

layerX/layerY是只读属性,返回点击的目标对象相对于当前层的水平/垂直坐标。——(MDN-MouseEvent.layerX

简单可以理解为:

  • 返回相对点击的元素相对于其父级元素(有定位属性)的坐标
  • 如果点击的元素以及父级元素都没有定位属性,那就返回相对于body标签的坐标
  • 如果点击的元素自身有定位属性返回的就是相对于自身的坐标

下面就来验证一下:

首先准备一个测试页面,其对应的CSS和HTML如下:

CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
body {
  height: 3000px;
}

#test1 {
  background-color: skyblue;
  width: 450px;
  height: 450px;
  padding: 25px;
  border: solid 3px black;
}

#test2 {
  background-color: tomato;
  width: 150px;
  height: 150px;
  padding: 10px;
  border: solid 8px black;
}

HTML:

1
2
3
<div id="test1">
  <div id="test2"></div>
</div>

document对象添加一个点击事件

1
2
3
document.addEventListener('click',function(e) {
  console.log('layerX:' + e.layerX, 'layerY:' + e.layerY);
});

截图

如果点击的元素以及父级元素都没有定位属性,那就返回相对于body标签的坐标

现在点击id为test2元素的左上角

截图

输出数据:

  • layerX:36 layerY:36

此处的36是这样的来的,如下图所示

截图

当元素的父级有定位属性时,以父级的左上角为原点:

修改CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#test1 {
  position: relative;
  top: 30px;
  left: 30px;
  background-color: skyblue;
  width: 450px;
  height: 450px;
  padding: 25px;
  border: solid 3px black;
}

#test2 {
  background-color: tomato;
  width: 150px;
  height: 150px;
  padding: 10px;
  border: solid 8px black;
}

和刚才一样点击id为test2元素的左上角,输出:

  • layerX:28 layerY:28

此时因为test2的父级元素test1有了定位属性,所以layerX/layerY输出的坐标就变为相对父级元素的左上角为原点的坐标。

如果点击的元素自身有定位属性返回的就是相对于自身的坐标

再次修改CSS:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#test1 {
  position: relative;
  top: 30px;
  left: 30px;
  background-color: skyblue;
  width: 450px;
  height: 450px;
  padding: 25px;
  border: solid 3px black;
}

#test2 {
  position: absolute;
  top: 5px;
  left: 5px;
  background-color: tomato;
  width: 150px;
  height: 150px;
  padding: 10px;
  border: solid 8px black;
}

和刚才一样点击id为test2元素的左上角,输出:

  • layerX:0 layerY:0

此时test2自身有了定位属性,所以layerX/layerY输出的坐标就变为相对自身元素左上角为原点的坐标。

总结

  • offsetX/offsetY:返回的是点击时候相对点击的元素左上角的相对位置(包含外边距)的坐标。
  • pageX/pageY:返回的是整个文档的坐标,如果此时页面比较长可以获取文档中鼠标的坐标。
  • clientX/clientY:返回的是鼠标点击的时候光标浏览器可视范围相对左上角的坐标。
  • screenX/screenY:返回的是鼠标点击的时候光标相对屏幕左上角的坐标。
  • layerX/layerY:往上找有定位属性的父元素的左上角(自身有定位属性的话就是相对于自身),都没有的话,就是相对于body的左上角的坐标。

参考文献