如何延迟路口观察器 API

Luk*_*uke 5 javascript settimeout intersection-observer

情况

我在页面顶部有一个固定的导航栏。当您向下滚动页面的不同部分时,导航栏会动态更新(下划线和突出显示)。您还可以单击导航栏上的某个部分,它将向下滚动到该部分。

这是使用交集观察器 API 来检测它所在的部分并使用scrollIntoView 滚动到每个部分来完成的。

问题

假设您位于第 1 部分,单击最后一个部分 5,页面就会向下滚动到中间的所有其他部分。滚动速度很快,并且当滚动时,交叉点观察器会检测到所有部分,因此导航会更新。当每个导航项经过每个相应部分时,您最终会得到导航快速变化的效果。

目标

如果该部分仅在帧中持续一毫秒,如何延迟交叉口观察器触发菜单更改?快速滚动时,导航栏仅应在滚动停止在某个部分后更新。

代码设置

const sectionItemOptions = {
  threshold: 0.7,
};

const sectionItemObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {

    if (entry.isIntersecting) {
      // select navigation link corresponding to section

    } else {
      // deselect navigation link corresponding to section

    }
  });
}, sectionItemOptions);

// start observing all sections on page
sections.forEach((section) => {
  sectionItemObserver.observe(section);
});
Run Code Online (Sandbox Code Playgroud)

想法

我的第一个想法是设置一个 setTimeout,以便导航在超时完成之前不会更改,然后如果该部分在超时完成之前离开屏幕,则取消超时。但由于超时是在 forEach 循环中,所以这不起作用。

const sectionItemObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach((entry) => {

    let selectNavTimeout

    if (entry.isIntersecting) {

      // Set timeout when section is scrolled past
      selectNavTimeout = setTimeout(() => {
        // select navigation link corresponding to section
      }, 1000)

    } else {
      // deselect navigation link corresponding to section
      // cancel timeout when section has left screen
      clearTimeout(selectNavTimeout)
    }
  });
}, sectionItemOptions);
Run Code Online (Sandbox Code Playgroud)

任何其他想法将不胜感激!谢谢 :)

Cre*_*ing 5

我有同样的问题。我最终使用了该setTimeout方法。您需要将超时与条目目标关联起来,前提是每个条目目标都有一些唯一的 ID。例如,假设我们将节点与id属性相交:

    let timeouts = {};
    const observer = new IntersectionObserver((entries, ob) => {
        for (const e of entries) {
            if (e.isIntersecting) {
                timeouts[e.target.id] = setTimeout(() => {
                    ob.unobserve(e.target)

                    // handling

                }, 1000)  // delay for 1 second
            } else {
                clearTimeout(timeouts[e.target.id])
            }
        }
    }, options)
Run Code Online (Sandbox Code Playgroud)


Luk*_*uke 0

经过大量的头脑风暴,我想出了一个想法,虽然并不能完全回答延迟 Intersection Observer API 的问题,但它确实解决了导航栏闪烁的问题。

导航项的突出显示是通过在其上添加“is-active”类然后对其应用 CSS 来完成的。由于“is-active”类仅在导航项上出现一瞬间,因此您可以使用 CSS 关键帧来延迟 CSS 样式的应用。当延迟完成时,“is-active”类不会出现在导航项上,并且样式不会更改。

保持原来的JS不变,这是使用的CSS

.is-active {
  animation: navItemSelected;
  animation-duration: 0.3s;
  // delay longer than the time nav item is in frame
  animation-delay: 0.1s;
  // fill mode to hold animation at the end
  animation-fill-mode: forwards;
}

@keyframes navItemSelected {
  // default non-selected style of nav item
  from {
    font-style: normal;
    opacity: 0.5;
  }
  // highlighted style of nav item
  to {
    font-style: italic;
    opacity: 1;
  }
}
Run Code Online (Sandbox Code Playgroud)