IntersectionObserver,元素是否在视口内

传统方式

监听 scroll 事件,调用指定元素 getBoundingClientRect 方法,再判断元素是否在视口内;如果是嵌套滚动,则需要多级监听,多级判断,计算量很大,可能影响性能。

(function () {
  const target = document.querySelector('.target');
  const tip = document.querySelector('.tip');

  let el = target;
  while (el.parentNode) {
    el.parentNode.addEventListener('scroll', scroll);
    el = el.parentNode;
  }

  // 滚动事件
  function scroll() {
    tip.innerHTML = isVisible(target) ? '出现' : '隐藏';
  }

  // 元素是否可见
  function isVisible(target) {
    let el = target;
    while (el) {
      if (!inView(el)) return false;

      el = el.parentElement;
    }
    return inView(target, target.parentElement.getBoundingClientRect());
  }

  // 元素是否在指定视口之内,只作了y轴判断
  function inView(target, view = { top: 0, bottom: innerHeight }) {
    const { top, bottom } = target.getBoundingClientRect();
    return (
      (top >= view.top && top <= view.bottom) ||
      (bottom >= view.top && bottom <= view.bottom) ||
      (top <= view.top && bottom >= view.top) ||
      (bottom <= view.top && top >= view.top)
    );
  }

  window.addEventListener('load', scroll);
})(window);

IntersectionObserver

提供了一种异步观察目标元素与其祖先元素或顶级文档视窗(viewport)交叉状态的方法。祖先元素与视窗(viewport)被称为根(root)。

方法

const observe = new IntersectionObserver(callback[, options]);

IntersectionObserver 接收两个参数,一个监听到变化时触发的回调函数 callback,另一个配置对象 options

const target = document.querySelector(selector);

observe.observe(target); // 添加观察元素

observe.unobserve(target); // 移出观察元素

observe.disconnect(); // 关闭观察对象

callback 参数

callback 一般触发两次(目标元素进入视口,目标元素离开视口),有两个参数

  • entries 是一个 IntersectionObserverEntry 对象的数组;
  • observer 当前观察器的实例;

IntersectionObserverEntry

属性有很多,其中 isIntersecting 是一个 boolean 值,表示目标是否是视口范围内。

完整代码

const target = document.querySelector('.target');
const tip = document.querySelector('.tip');
const observe = new IntersectionObserver(entries => {
  for (const entry of entries) {
    tip.innerHTML = entry.isIntersecting ? '展示' : '隐藏';
  }
});
observe.observe(target);

以上代码完全可以实现传统方式判断目标是否进入视口功能,兼容性方面IE浏览器全军覆没。

posted @ 2022-03-14 23:42  梦渊同学  阅读(284)  评论(0编辑  收藏  举报