【问题标题】:Unable to clear interval when element is outside viewport in Intersection Observer API当元素在 Intersection Observer API 中的视口之外时无法清除间隔
【发布时间】:2021-08-04 16:44:42
【问题描述】:

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

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

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

我在这里做错了什么?

这是sn-p:

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>

【问题讨论】:

  • 每次交集改变时都会调用回调,所以intervalVar被重新声明(它也为每个条目重新声明)。要么为每个需要的条目创建一个包含间隔 id 的 Map,或者更好的是,根本不在观察者回调中使用间隔。只需在item.isIntersecting 为真时触发一个函数,并在它为假时触发它。该函数可以在内部跟踪 id 并根据是否使用 true 或 false 来决定如何处理这些 id。
  • 你能提供一个sn-p吗?

标签: javascript jquery setinterval intersection-observer


【解决方案1】:

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

我在来自交叉点观察者回调的条目参数的条目和间隔 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>

【讨论】:

  • 哇。我一直避免使用 Map 对象,因为我认为它非常复杂,但它非常简单。我现在了解完整的代码。很光滑。谢谢老兄。
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-04
  • 1970-01-01
相关资源
最近更新 更多