JavaScript中判断元素是否在可视区域内

1.有什么应用

  • 懒加载
  • 列表的无限滚动
  • 计算广告元素的曝光情况

2.方法1-----使用offsetTop、scrollTop

offsetTop、scrollTop属于三大家族的内容,详情见https://blog.youkuaiyun.com/fageaaa/article/details/145728760

思路:元素的offsetTop-页面的scrollTop<=页面的高度

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <style>
      .area1,
      .area3 {
        width: 100%;
        height: 1200px;
        background-color: aqua;
      }
      .box {
        width: 100%;
        height: 100px;
        background-color: red;
      }
    </style>
  </head>
  <body>
    <div class="area1"></div>
    <div class="area2 box"></div>
    <div class="area3"></div>
    <script>
      function isInViewPortOfOne(el) {
        // 下面是浏览器视口的高度的兼容性写法
        const viewPortHeight =
          window.innerHeight ||
          document.documentElement.clientHeight ||
          document.body.clientHeight;
        const offsetTop = el.offsetTop;
        const scrollTop = document.documentElement.scrollTop;
        const top = offsetTop - scrollTop;
        //注意这里只是个简略方式,没考虑el的边框
        return top <= viewPortHeight && top + el.clientHeight >= 0;
      }

      let box= document.querySelector(".box");
      window.addEventListener("scroll", function () {
        if (isInViewPortOfOne(box)) {
          console.log("box元素在可视区域内");
        } else {
          console.log("box元素不在可视区域内");
        }
      });
    </script>
  </body>
</html>

3.方法2-----getBoundingClientRect

getBoundingClientRect函数返回值是一个 DOMRect对象,拥有left, top, right, bottom, x, y, width, 和 height属性。详情见https://blog.youkuaiyun.com/fageaaa/article/details/145728760
思路:top大于等于0;left大于等于0;right小于等于viewWidthbottom小于等于viewHeight

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
    );
}

4.方法3-----Intersection Observer

前面两种方式需要一直监听,就算用了防抖节流也要一直监听(只不过性能会好一点)。所以Intersection Observer这个方法性能上会更好!!!

浏览器提供了一种异步观察目标元素与祖先元素(或顶级文档的视口)交叉状态变化的方法。IntersectionObserver详细用法见https://blog.youkuaiyun.com/fageaaa/article/details/145741778

<head>
    <meta charset="UTF-8" />
    <title>Title</title>
    <style>
      .area1,
      .area3 {
        width: 100%;
        height: 1200px;
        background-color: aqua;
      }
      .box {
        width: 100%;
        height: 100px;
        background-color: red;
      }
    </style>
  </head>
  <body>
    <div class="area1"></div>
    <div class="area2 box"></div>
    <div class="area3"></div>
    <script>
      let box = document.querySelector(".box");
      //它提供了一种异步观察目标元素与祖先元素(或顶级文档的视口)交叉状态变化的方法。
      // 这个API的出现主要是为了高效解决在网页开发中需要频繁判断元素是否进入“视口”(viewport)的问题。
      // 相比于传统的依赖scroll事件和getBoundingClientRect方法,Intersection Observer API在性能上有显著的优势
      let intersectionObserver = new IntersectionObserver(function (el) {
        if (el[0].intersectionRatio <= 0) {
          console.log("元素彻底离开可视区");
        } else {
          console.log("元素进入可视区");
          //进入可视区之后,资源已经下载好,就不需要再进行监视了
          intersectionObserver.unobserve(box);
        }
      });
      intersectionObserver.observe(box);
    </script>
  </body>
在 UniApp 移动端判断元素是否可视区域内,可借助 UniApp 提供的 `createIntersectionObserver` API 来实现,该 API 能监听目标元素可视区域的交叉状态。 示例代码如下: ```javascript // 在页面的生命周期函数中使用 export default { onReady() { // 创建一个 IntersectionObserver 实例 const observer = uni.createIntersectionObserver(this); // 选择要观察的目标元素,这里以 id 为 target-element 的元素为例 observer.relativeToViewport().observe('#target-element', (res) => { if (res.intersectionRatio > 0) { // 元素可视区域内 console.log('元素可视区域内'); } else { // 元素不在可视区域内 console.log('元素不在可视区域内'); } }); } } ``` 在上述代码里,先调用 `uni.createIntersectionObserver` 方法创建一个 `IntersectionObserver` 实例,再使用 `relativeToViewport` 方法指定参考区域可视区域,接着用 `observe` 方法指定要观察的目标元素。当目标元素可视区域发生交叉时,回调函数会被触发,通过 `res.intersectionRatio` 判断元素是否可视区域内。 此外,也可在 UniApp 里使用 JavaScript 的 `getBoundingClientRect` 方法来判断元素是否可视区域内,与在普通网页中的使用方式类似。示例代码如下: ```javascript export default { methods: { isInViewPort(element) { const viewWidth = uni.getSystemInfoSync().windowWidth; const viewHeight = uni.getSystemInfoSync().windowHeight; const { top, right, bottom, left } = element.getBoundingClientRect(); return top >= 0 && left >= 0 && right <= viewWidth && bottom <= viewHeight; }, checkElementVisibility() { const element = document.getElementById('target-element'); if (element) { const isVisible = this.isInViewPort(element); if (isVisible) { console.log('元素可视区域内'); } else { console.log('元素不在可视区域内'); } } } }, onReady() { this.checkElementVisibility(); } } ``` 在这个示例中,定义了 `isInViewPort` 方法用于判断元素是否可视区域内,然后在 `checkElementVisibility` 方法里调用该方法,在页面的 `onReady` 生命周期函数中执行检查操作。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

太阳与星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值