likes
comments
collection
share

图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

作者站长头像
站长
· 阅读数 11

前言: 在上一篇文章 🎁如何实现原生 JS 的拖拽效果中,我们使用到了 MouseEvent 事件对象身上的 clienX 的属性,但同时我也注意到了事件对象身上关于 X 的相关属性还有很多,并且在移动端开发中,这些属性需要频繁的用到,所以来总结一下这些关于 X 轴身上各个属性含义的不同。


一. 前期准备

  1. 在进行下面的内容之前,我希望大家先把传统数学中坐标轴的 y 轴方向和 x 轴的正轴负轴方向的概念遗忘掉。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  2. 对于客户端来讲,它们采用坐标系的方向有些许不同,如下图。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X 造成这个的原因其实也很简单,你想一下,对于用户来讲,有用的区域就是我们的整块屏幕,如果负轴的话就已经超出屏幕之外了(下图的黄色区域),对我们没有任何实际的意义。所以一般来讲关于屏幕坐标时,我们就默认规定从左角开始向下为 y 坐标轴。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  3. 对上面的解释其实不太严谨,但是可以让你有个大概的认知,从而方便我们再讲解下面几个属性不同时,让你有更深刻的理解。

  4. 让我们制造一个点击事件来引入我们今天的各个属性值。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  5. 可以看到右侧出现了很多关于 X,Y 的属性,接下来我们一个一个去了解它们各自到底代表着什么。

二. ScreenX 、ScreeY

  1. 其实从 Screen 这个单词的意思就能大概猜出来它代表的是什么意思。“屏幕” 嘛!那肯定是相对于屏幕来讲的啊。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  2. 最开始我在这里迷惑的是下面这种情况,当我把浏览器窗口缩小的时候,这个 screenY 是代表着那根线的距离呢?🤔 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  3. 我们验证一下这个猜想,可以看出虽然我们浏览器窗口缩小了,但是我们的 screenY 依旧代表着我们点击的点到整块电脑屏幕显示器的最顶部的距离。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

三. LayerX、LayerY

  1. 这个属性需要搭配使用 position 定位的几个值才能看出不一样的地方。大致概念为:如果元素自身的 position 属性不是 static,那么这个元素的 layer 就相对于它自身的左上角开始计算。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  2. 如下图所示,当我点击了该元素内部以后,它的 layerXlayerY 大小计算就是从左上角开始的。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  3. 同理,如果自身没有设置定位的相关属性,也就是元素本身 position 属性为 static。那么它会向上寻找离得最近的 position 不为 static 的元素,然后从相对于那个元素的左上角的距离开始计算。如果都没有,那么最终寻找到 body 标签结束。

三. clientX、clientY

  1. 仅从 client 这个单词来讲,如果你看过我之前的文章,那么我想你大概可以猜出来 clienXclientY 代表着什么,它们之间其实有异曲同工之处,不然为啥都叫 client 呢? 在这个场景,client 这个单词其实代表着 用户端(代表浏览器窗口)可视区域的意思。

  2. 如果你还不了解什么是客户端可视区域,那么我强烈建议你点开下面的文章去了解一下,尤其你以后考虑接触移动端开发的话,那么下面三个属性是你必须知道的知识点。 🫱你必须知道的clientWidth, offsetWidth, scrollWidth.

  3. 回到 clientXclientY 上,在这里明确比告诉大家一个概念:这两个值只关心用户当前屏幕(浏览器窗口)上能够看到的区域,并且从当前区域的左上角开始计算距离。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  4. 什么意思?我们都知道当内容宽度或者高度超出父容器设置的宽度高度的时候,会引发溢出。常见处理溢出的方案就是设置它的 overflow 属性,如 overflow-auto 等。

  5. 我们先创建一个溢出的场景,并且我把 clientX 的数值展示到了页面上。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  6. 可以看出其实我在滑动的时候已经多次点击触发 onMouseDown 事件了,只不过对于我们来讲,我们能看到的区域仅仅只是容器最左边开始。(溢出的部分我们是看不到的,我们 client 也不关心那溢出的那部分的距离。) 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  7. 同理 clientY 也是不关心溢出的部分,只关心能看到的那部分。

四. PageX、 PageY

  1. 从上面刚刚讲过的 clientYclientX 不关心溢出的那部分。哪有人关心溢出的那部分距离吗?你别说还真有,那就是 pageXpageY

  2. 因为这个属性是相对于整个文档的左上角来开始计算的,所以我们上面的溢出例子还触发不了这个属性的变化。 我们这里借助 MDN 的页面来讲解,由上面 clientY 的知识可以得到,当我们页面没滚动的时候,这个距离其实就是 clientY 的距离。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  3. 你可能会疑惑,奇怪,我们不是在讲解 PageY 吗?怎么又回到 clientY 了?其实一点也不奇怪,在这种情况下,我们的 pageYclientY 是一模一样的,没有任何区别。

  4. 但是!一旦发生了下面的情况,由于内容溢出导致页面发生了滚动。如下图: 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X 那么我们的 PageY 属性记录的值就变成了滚动的距离+ clientY的距离。如果你知道 scroTop 所代表的含义,那么你可以很快得出下面的计算方式。 pageY = scroTop + clientY 如果你还不了解 scroTop 的相关知识,没关系,我同样讲过,你可以点击这里去自行了解。 🫱关于使用 scrollTop 来完成 tab 栏的交互

  5. pageX 同理,是发生在水平方向溢出的情况,这里就不再过度赘述。

五. offsetX 、offsetY

  1. 我们恢复到最基本的样式。此时黑块没有任何 border 属性。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  2. 那么此时的 offsetXoffsetY 就代表着距离自身左上角的距离。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  3. 如果此时我们加上 10px 的border 的话,情况就会发生变化。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X 聪明的你可能已经看出来了,它起点的计算向内部压缩了一个 border 的宽度 。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  4. 这里其实还有一个关键知识点,不知道你发现了没,这个属性和 layerXlayerY 很相似,我们测试一下当元素自身设置 relative 的时候,它的 layer 属性也是相对于自身开始的。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X offsetXlayerX 有区别吗?

  5. 这里直接揭晓答案,即使我们设置了 border, layer 的属性也是没有受到任何影响的,依旧从元素最左上角开始计算距离。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

六. X、Y

  1. 是的,你没看错,就只是单纯的这两个字母,但是这两个属性也确确实实存在。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

  2. 经过查阅可知,它其实就是 clientX,所以我们不再重复。 图解鼠标事件的 ScreenX ,LayerX,clientX,PageX,offsetX,X

七. 总结:

这篇文章是由我随手做的笔记改编而来,笔记内容比较粗糙,转化为文章后个人感觉又重新复习了一遍,加深了很大的印象。如果该文章能帮助到一些人,也是一件幸事。

可能我以后也会经常来翻阅自己的这篇文章~这几个属性确实容易搞混🤔