【前端学习——js篇】11.元素可见区域

具体见:https://github.com/febobo/web-interview

11.元素可见区域

①offsetTop、scrollTop

offsetTop,元素的上外边框至包含元素的上内边框之间的像素距离,其他offset属性如下图所示:

下面再来了解下clientWidthclientHeight

  • clientWidth:元素内容区宽度加上左右内边距宽度,即clientWidth = content + padding
  • clientHeight:元素内容区高度加上上下内边距高度,即clientHeight = content + padding

这里可以看到client元素都不包括外边距

最后,关于scroll系列的属性如下:

  • scrollWidthscrollHeight 主要用于确定元素内容的实际大小

  • scrollLeftscrollTop 属性既可以确定元素当前滚动的状态,也可以设置元素的滚动位置

    • 垂直滚动 scrollTop > 0
    • 水平滚动 scrollLeft > 0
  • 将元素的 scrollLeftscrollTop 设置为 0,可以重置元素的滚动位置

  • 上述属性都是只读的,每次访问都要重新开始


判断页面触底我们需要先了解一下下面几个属性:

  • scrollTop:滚动视窗的高度距离window顶部的距离,它会随着往上滚动而不断增加,初始值是0,它是一个变化的值
  • clientHeight:它是一个定值,表示屏幕可视区域的高度;
  • scrollHeight:页面不能滚动时也是存在的,此时scrollHeight等于clientHeight。scrollHeight表示body所有元素的总长度(包括body元素自身的padding)

可视区域即我们浏览网页的设备肉眼可见的区域,如下图

在日常开发中,我们经常需要判断目标元素是否在视窗之内或者和视窗的距离小于一个值(例如 100 px),从而实现一些常用的功能,例如:

  • 图片的懒加载
  • 列表的无限滚动
  • 计算广告元素的曝光情况
  • 可点击链接的预加载
②实现方式

公式如下:

也就是元素距上外边框的距离 - 滚动视窗距window顶部的距离 ,是否超过了视窗高度。

el.offsetTop - document.documentElement.scrollTop <= viewPortHeight

代码实现:

function isInViewPortOfOne (el) {// viewPortHeight 兼容所有浏览器写法const viewPortHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight const offsetTop = el.offsetTopconst scrollTop = document.documentElement.scrollTopconst top = offsetTop - scrollTopreturn top <= viewPortHeight
}
③getBoundingClientRect

返回值是一个 DOMRect对象,拥有left, top, right, bottom, x, y, width, 和 height属性

const target = document.querySelector('.target');
const clientRect = target.getBoundingClientRect();
console.log(clientRect);// {
//   bottom: 556.21875,
//   height: 393.59375,
//   left: 333,
//   right: 1017,
//   top: 162.625,
//   width: 684
// }

属性对应的关系图如下所示:

当页面发生滚动的时候,topleft属性值都会随之改变。

如果一个元素在视窗之内的话,那么它一定满足下面四个条件:

  • top 大于等于 0
  • left 大于等于 0
  • bottom 小于等于视窗高度
  • right 小于等于视窗宽度

实现代码如下:

function isInViewPort(element) {const viewWidth = window.innerWidth || document.documentElement.clientWidth;const viewHeight = window.innerHeight || document.documentElement.clientHeight;const {top,right,bottom,left,} = element.getBoundingClientRect();return (top >= 0 &&left >= 0 &&right <= viewWidth &&bottom <= viewHeight);
}
④Intersection Observer

Intersection Observer 即重叠观察者,从这个命名就可以看出它用于判断两个元素是否重叠,因为不用进行事件的监听,性能方面相比getBoundingClientRect 会好很多。

使用步骤主要分为两步:创建观察者和传入被观察者

创建观察者

const options = {// 表示重叠面积占被观察者的比例,从 0 - 1 取值,// 1 表示完全被包含threshold: 1.0, root:document.querySelector('#scrollArea') // 必须是目标元素的父级元素
};const callback = (entries, observer) => { ....}const observer = new IntersectionObserver(callback, options);

通过new IntersectionObserver创建了观察者 observer,传入的参数 callback 在重叠比例超过 threshold 时会被执行`

关于callback回调函数常用属性如下:

// 上段代码中被省略的 callback
const callback = function(entries, observer) { entries.forEach(entry => {entry.time;               // 触发的时间entry.rootBounds;         // 根元素的位置矩形,这种情况下为视窗位置entry.boundingClientRect; // 被观察者的位置举行entry.intersectionRect;   // 重叠区域的位置矩形entry.intersectionRatio;  // 重叠区域占被观察者面积的比例(被观察者不是矩形时也按照矩形计算)entry.target;             // 被观察者});
};

传入被观察者

通过 observer.observe(target) 这一行代码即可简单的注册被观察者

const target = document.querySelector('.target');
observer.observe(target);
案例

例子创建了一个十万个节点的长列表,当节点滚入到视窗中时,背景就会从红色变为黄色。

<body><div class="container"></div>
</body>
    .container {display: flex;flex-wrap: wrap;}.target {margin: 5px;width: 20px;height: 20px;background: red;}

首先插入100000个div

	const container = document.querySelector(".container");// 插入 100000 个 <div class="target"></div>function createTargets() {const htmlString = new Array(100000).fill('<div class="target"></div>').join("");container.innerHTML= htmlString;}

判定target是否在视窗中,element是传入的target

 function isInviewPort(element){const viewWidth = window.innerWidth || document.document.clientWidth;const viewHeigth = window.innerHeight || document.documentElement.clientWidth;const { top,right,bottom,left} = element.getBoundingClientRect();return top >= 0 && left >=0 && right <= viewWidth && bottom <= viewHeigth;}

绑定滑轮事件

 this.addEventListener('scroll',() =>{console.log("scroll!");const target = document.querySelectorAll('.target')for(const element of target){if(isInviewPort(element)){element.style =  "background-color:yellow"}else{element.style =  "background-color:red"}}})

可以看到,没当滑动就会把所有target,依次传入isInviewPort,若在视窗中则改变颜色为黄色,否则改为红色。

通过上面的方法基本实现要求,但是有明显的卡顿,原因在于我们绑定了scroll事件,scroll事件伴随了大量的计算,会造成资源方面的浪费。

下面试试观察者的方法,首先创建一个观察者,然后给每个target进行绑定。

 const observer = new IntersectionObserver(getYellow, { threshold: 1.0 });const target = document.querySelectorAll('.target')for (const element of target) {observer.observe(element)}

最后使用getYellow回调函数实现对背景颜色改变。

 function getYellow(entries, observer) {for (const entry of entries) {let element = entry.target// console.log(element);if (isInviewPort(element)) {element.style = "background-color:yellow"} else {element.style = "background-color:red"}}}

还是有延迟,但是明显好很多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/573778.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux系统编程--信号

1、信号&#xff08;一&#xff09; 1.1、什么是中断 1.2、中断分类 1.3、信号 1.4、信号与中断 1.5、信号名称 1.6、进程对信号的三种响应 1.7、signal函数&#xff1a;注册信号 signal(SIGINT, handler);返回值是SIGINT所对应的处理程序 再调用一下signal(SIGINT, handler2…

前端实现浏览器自定义滚动条

前言&#xff1a; 最近有个项目&#xff0c;产品觉得浏览器默认滚动条太丑了。想美化一下&#xff0c;比如自定义颜色&#xff0c;加上圆角&#xff0c;宽高都要更改一下。我查了资料和文档总结了一下 写法&#xff0c;特此记录以便之后使用。 浏览器滚动条api 总结&#xff…

【计算机网络】启程

&#x1f4dd;本文介绍 本文为计算机网路系列的开始篇&#xff0c;会介绍一下使用的书籍和自己做的思维导图。 &#x1f44b;作者简介&#xff1a;一个正在积极探索的本科生 &#x1f4f1;联系方式&#xff1a;943641266(QQ) &#x1f6aa;Github地址&#xff1a;https://githu…

「18」如何让你直播间增加高级质感,效果滤镜是你不二选择?

「18」效果滤镜给你的布景增加质感&#xff0c;更具视觉效果 首先&#xff0c;安装&#xff08;模糊滤镜的‘streamfx’&#xff09;安装包。安装成功后&#xff0c;StreamFX 会出现在 OBS 的菜单栏上。在OBS软件里滤镜可分为效果滤镜和音视频滤镜。 一、音视频滤镜 在选择「…

【技巧】PyTorch限制GPU显存的可使用上限

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhang.cn] 从 PyTorch 1.4 版本开始&#xff0c;引入了一个新的功能 torch.cuda.set_per_process_memory_fraction(fraction, device)&#xff0c;这个功能允许用户为特定的 GPU 设备设置进程可使用的显存上限比例。 测试代…

刚刚,百度和苹果宣布联名

百度 Apple 就在刚刚&#xff0c;财联社报道&#xff0c;百度将为苹果今年发布的 iPhone16、Mac 系统和 iOS18 提供 AI 功能。 苹果曾与阿里以及另外一家国产大模型公司进行过洽谈&#xff0c;最后确定由百度提供这项服务&#xff0c;苹果预计采取 API 接口的方式计费。 苹果将…

管理阿里云服务器ECS -- 网站选型和搭建

小云&#xff1a;我已经学会了如何登录云服务器ECS了&#xff0c;但是要如何搭建网站呢&#xff1f; 老王&#xff1a;目前有很多的个人网站系统软件&#xff0c;其中 WordPress 是使用非常广泛的一款&#xff0c;而且也可以把 WordPress 当作一个内容管理系统&#xff08;CMS…

机器学习中的LightGBM模型及其优缺点(包含Python代码样例)

目录 一、简介 二、优缺点 三、样例代码 四、总结 一、简介 LightGBM&#xff08;Light Gradient Boosting Machine&#xff09;是一种基于梯度提升&#xff08;Gradient Boosting&#xff09;算法的机器学习模型。它是由微软团队于2017年开发的&#xff0c;旨在解决大规模…

Spring 事务传播行为

实现原理 : Aop (TransactionInterceptor) 实现 使用spring声明式事务注意事项 同一个bean中的方法调用必须重新声明一个bean调用、否则后续方法调用的事务默认使用第一个第二个不生效 package com.cloud.person.service.impl;import com.cloud.person.dao.S1Mapper; import…

win10怎么关闭自动更新,win10关闭自动更新步骤

不知道大家有没有碰到过这样的情况,就是有一位网友反映说最近买了一台新电脑,配置呢也很高,玩游戏呢也很流畅,不过有一件事情让他很头疼,就是这个电脑有的时候就会出现蓝屏,还提示修复什么的,并且呢越用越卡顿。出现这个问题的主要原因就是现在新的电脑一般用的都是win1…

CC1310F128RSMR Sub-1GHz超低功耗无线微控制器芯片

CC1310F128RSMR QFN-32 Sub-1GHz超低功耗无线微控制器 CC1310F128RSMR是一款低成本、 超低功耗、Sub-1 GHz射频器件&#xff0c;它是Simplel ink微控制器(MCU)平台的一部分。该平台由Wi- Fi组成、蓝牙低功耗&#xff0c;Sub-1 GHz&#xff0c;以太网&#xff0c;Zigbee线程和主…

数字身份的革命:解锁 Web3 的身份验证技术

引言 随着数字化时代的到来&#xff0c;个人身份认证成为了日常生活和商业活动中不可或缺的一部分。传统的身份验证方式存在着安全性低、易伪造、不便利等问题&#xff0c;因此&#xff0c;人们迫切需要一种更安全、更便捷的身份验证技术。在这样的背景下&#xff0c;Web3的身…