当元素在 Intersection Observer 中的视口外时无法清除间隔 API

Unable to clear interval when element is outside viewport in Intersection Observer API

我正在试用 Intersection Observer API,但是当我使用 setInverval 时,我遇到了死胡同。

所以我有这个 div,它的宽度和高度都是 500 像素。如果 div 在视口中,我想触发 setInterval 每 3 秒记录一次。但是,如果我滚动并且 div 在视口之外,我想清除该间隔。也就是说,停止间隔并完全停止记录。

现在当我滚动并且 div 在视口中时,setInterval 和日志记录开始但是如果我再次滚动并且 div 不在视口中 setInterval 并且记录不会停止。

我做错了什么?

这是片段:

const mainContainer = document.querySelector('#main-container');

const callback = (entries, observer) => {

  entries.forEach(item => {

    let intervalVar;

    if (item.isIntersecting) {

      intervalVar = setInterval(() => {

        console.log('div is in viewport');

      }, 3000);

    } else {

      console.log('div is not in viewport');

      clearInterval(intervalVar);

    }

  })
};


const options = {
  threshold: 0.1
};

const observer = new IntersectionObserver(callback, options);
observer.observe(mainContainer);
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

<div id="main-container" style="width: 540px; height: 440px;"></div>

所以,这是解决问题的一种方法。

我在交集观察者回调的条目参数和间隔 ID (intersections) 之间创建了一个 Map

我创建了一个函数 (intersectionChanged),它会为交集观察者回调的条目参数中的每个条目调用。它检查条目是否相交,以及我们是否有间隔 ID。如果两者都为真,它会清除现有间隔并添加一个新间隔。如果它是新相交的,它会添加一个新的间隔。如果它不相交,并且有一个间隔 id,它会清除该间隔。否则,它什么都不做。换句话说,如果它不相交,并且不存在间隔id,它什么都不做。

使用您已经构建的代码很容易将它们组合在一起。

const mainContainer = document.querySelector('#main-container');
const intersections = new Map();
const intersectionChanged = function (entry) {
  if (entry.isIntersecting && intersections.get(entry.target) != null) {
    clearInterval(intersections.get(entry.target));
    intersections.set(entry.target, setInterval(() => {
        console.log('div is in viewport');
      }, 3000));
  } else if (entry.isIntersecting) {
    intersections.set(entry.target, setInterval(() => {
        console.log('div is in viewport');
      }, 3000));
  } else if (!entry.isIntersecting && intersections.get(entry.target) != null) {
    console.log('div is not in viewport');
    clearInterval(intersections.get(entry.target));
  }
};
const callback = (entries, observer) => {
  entries.forEach(intersectionChanged);
};

const options = {
  threshold: 0.1
};

const observer = new IntersectionObserver(callback, options);
observer.observe(mainContainer);
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

<div id="main-container" style="width: 540px; height: 440px;border:1px solid black"></div>