一文彻底搞懂图解事件的坐标以及dom事件的属性,可视区域,

一.鼠标事件获取的位置信息

来源:一般是鼠标事件如click、dbclick、mousemove、mouseover等获取的位置信息。

事件对象可作为参数掺入事件处理函数中,事件对象中包含了许多有用的属性,例如:

  • clientX 和 clientY:鼠标相对于浏览器视口的位置。
  • pageX 和 pageY:鼠标相对于整个文档的位置。
  • screenX 和 screenY:鼠标相对于用户屏幕的位置。
  • button:表示哪个鼠标按钮被按下(0 = 左键,1 = 中键,2 = 右键)。
  • target:事件的目标元素。

下面对其中的坐标进行详细的介绍

如上图所示,假设页面中灰色圆点是鼠标点击处,黄色区域是鼠标触发事件对象

综上:注意这里的坐标是鼠标点击的点,每次点击的不一样,坐标也是不一样的,即使你内容区还在原来的位置。     此外::::::注意page和client的区别::::::。

1、screenX 和screenY

  • 参照点:电脑屏幕左上角

  • screenX:鼠标点击位置相对于电脑屏幕左上角的水平偏移量

  • screenY:鼠标点击位置相对于电脑屏幕左上角的垂直偏移量

2、clientX和clientY

  • 参照点:浏览器内容区域左上角

  • clientX:鼠标点击位置相对于浏览器可视区域的水平偏移量(不会计算水平滚动的距离

  • clientY:鼠标点击位置相对于浏览器可视区域的垂直偏移量(不会计算垂直滚动条的距离

3、pageX和pageY

  • 参照点:网页的左上角

  • pageX:鼠标点击位置相对于网页左上角的水平偏移量,也就是clientX加上水平滚动条的距离

  • pageY:鼠标点击位置相对于网页左上角的垂直平偏移量,也就是clientY加上垂直滚动条的距离

4、offsetX和offsetY

  • 参照点:父元素

  • offsetX:鼠标点击位置相对于触发事件对象的水平距离

  • offsetY:鼠标点击位置相对于触发事件对象的垂直距离

二.dom事件的属性

1.位置和尺寸

都没有xxxright 和xxxbottom属性。

  • offset系列 经常用于获得元素位置一共有5个相关值: offsetHeight、offsetWidth、offsetParent、offsetLeft、offsetTop  offsetParent 很有用,因为 offsetTopoffsetLeft 都是相对于其内边距边界的。
  • client经常用于获取元素大小 clientWidth、clientHeight、clientTop、clientLeft
  • scroll 经常用于获取滚动距离 scrollTop、scrollLeft、scrollHeight、scrollWidth

scroll:滚动对象     offset:相对于版面或上层控件的位置       client:对象自身

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

clientHeight:是一个dom属性,表示元素的可见高度。计算公式:内容区域 + padding(top + bottom)-----------注意:不包括边框,和滚动条

clientTop:是一个只读的属性,表示元素的上边框的宽度,单位为像素,通常在计算元素的可视区域时候考虑一下,但是一般边框很小无需考虑。

clientLeft:表示左边框的宽度,clientTop表示上边框的宽度,但是没有clientRight,clientBottom

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

offsetheight:是一个dom属性,表示元素的高度。计算公式:内容区域 + 内边距(top + bottom) + 边框 ----------注意:包含边框

offsetTop:是一个只读属性,表示当前元素的上边框相对于父亲的顶部边缘的距离,也就是上边距。

offsetLeft:是一个只读属性,表示当前元素的左边框到父亲的左边缘的间距,也就是左边距。

offsetParent:是一个 DOM 元素的属性,用于获取元素的最近的定位父元素。该定位父元素是具有position属性值为relativeabsolutefixed的元素。如果没有这样的父元素,则返回null。

offsetWidth:是一个DOM元素的属性,获取元素的布局宽度。

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

scrollHeight:是一个dom属性,表示元素的完整高度,计算公式:内容区域 + 内边距 + 溢出部分----------注意:也不包括边框,在没有滚动条时候和clientHeight一样。

scrollWidth:返回一个元素的内容宽度,表示元素完整的宽度,计算公式同上。

scrrollLeft:返回一个元素的水平滚动位置,即元素内容向左滚动的位置,如果没有横向滚动条他的值就是为0。

scrollTop:返回元素垂直滚动的位置,即元素向上滚动的像素值。如果没有纵向滚动条,则值为0。

2.常用方法

(1)getBoundingClientRect:是DOM元素的一个方法,返回一个DOMRect对象,包含元素的大小及其相对于视口的位置。

兼容性:IE5以上的版本。

返回的坐标是相对于视口的,因此在页面滚动时,值会变化。他包含以下属性:

  • top: 元素上边框到视口顶部的距离,如果元素滚动顶部边框超过顶部,则为负值。
  • right: 元素右边框相对于视口左侧的距离,如果元素滚动底部边框超过顶部,则为负值。    ////////////////注意:top和bottom都是相对于可视区域顶部来计算的
  • bottom: 元素底边框相对于视口顶部的距离。
  • left:元素左边框相对于视口左侧的距离。
  • width: 内容的宽度,包含padding和border
  • height: 内容的高度,,同上

 注意:这里的视口原点通常是浏览器页面的左上角,left就是dom的左边框相对于浏览器左边缘部分的距离,Top是距离浏览器顶部的距离。

方式1:倘若判断一个元素在不在可视区域内

1
2
3
4
5
6
7
8
9
function isElementInViewport(el) {
    const rect = el.getBoundingClientRect();
    return (
        rect.top >= 0 &&
        rect.left >= 0 &&
        rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&   //////////浏览器窗口的高度和宽度的获取采用了兼容性处理
        rect.right <= (window.innerWidth || document.documentElement.clientWidth)
    );
}

上面的代码默认可视区域为整个浏览器(减去控制台的高度),然而通常我们的滚动区域只是页面中的一小块,这时候需要优化一下代码,如下:

1
2
3
4
5
6
7
8
9
10
11
function isElementInScrollableArea(el, scrollableArea) {
    const rect = el.getBoundingClientRect();
    const scrollableRect = scrollableArea.getBoundingClientRect();
 
    return (
        rect.top >= scrollableRect.top &&
        rect.left >= scrollableRect.left &&
        rect.bottom <= scrollableRect.bottom &&
        rect.right <= scrollableRect.right
    );
}

通常情况下:在数据懒加载的时候我们遇到的都是纵向滚动区域,也就是不需要关注左右距离,并且滚动区域的高度也是固定的,因此只需要关注上下即可,左右的判断可以省略。

具有如下的缺点:

     a.重新渲染页面‌:当同时获取多个元素的属性时,浏览器需要重新渲染页面。getBoundingClientRect()方法会获取元素的宽、高、左、右等属性,这些属性的获取需要浏览器重新渲染整个页面,从而影响性能。

     b.计算位置不精确‌:getBoundingClientRect()方法计算的是元素到窗口边界的距离,而不是屏幕中实际可见的位置。如果计算的位置信息不精确,可能会导致性能损失。

方式:2:通过元素的位置信息和滚动条滚动的高度

首先了解一下这个图的意义。

1
2
3
4
5
6
7
8
function isInViewPort(element) {
  // 获取可视窗口的高度。
  const scrollHeight= window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
  // 获取滚动条滚动的高度
  const scrollTop = document.documentElement.scrollTop;
  // 获取元素偏移的高度。就是距离可视窗口的偏移量。
  const offsetTop = element.offsetTop;
  return offsetTop - scrollTop <= scrollHeight;<br> }

此外:getBoundingClientRect并不能满足所有情况,甚至说,它只能满足一种情况的判断,那就是需要判断的那个dom节点,它只身处在一个滚动条的情况下。什么意思呢,就是它所有的祖先节点,加起来的滚动条只有1个,如果它父节点有滚动条,父父节点也有滚动条,那这种方法就不好用了。

方式3:Intersection Observer

Intersection Observer是一个现代的Web API,用于异步观察目标元素与祖先元素或视口的交叉状态。它可以帮助你判断元素是否在可视区域内,从而实现惰性加载、无限滚动等功能。举例使用步骤如下:

复制代码
// 1. 创建 IntersectionObserver 实例
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    // 2. 处理回调
    if (entry.isIntersecting) {
      console.log('元素进入可视区域');
    } else {
      console.log('元素离开可视区域');
    }
  });
}, {
  root: null, // 默认视口
  rootMargin: '0px', // 无额外边距
  threshold: 0.5 // 50%可见时触发
});

// 3. 观察目标元素
const targetElement = document.querySelector('#target');
observer.observe(targetElement);

// 4. 停止观察(可选)
// observer.unobserve(targetElement);
// observer.disconnect();
复制代码

参数解释:

  • root:参考元素,默认为视口---------如果,你将 root 设置为 null,那么观察者将使用浏览器的视口(viewport)作为根元素。这意味着目标元素的可见性将相对于浏览器窗口来判断。

  • rootMargin:参考元素的边距,扩展或缩小交叉区域。

  • threshold:触发回调的可见比例阈值,可以是单个值或数组。

你在第三步骤可以通过滚动事件或者点击事件建立了observe连接之后,后面将会自动检测目标元素是否离开和进入可视区域,类似于eventbus这种。

(2)scrollIntoview

 

posted @   122www  阅读(128)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示