当元素已经在视口中时触发 IntersectionObserver

s1g*_*r1d 8 javascript intersection-observer

IntersectionObserver被触发时的元件是在视口中一定量(0-100%)可见。这意味着,当元素在视口中已经 100% 时,它不再触发,因为阈值没有变化。

我有一个高度为 的元素,当我滚动该元素时200vh,我希望IntersectionObserver触发。所以元素总是 100% 在视口内。

有没有办法在滚动元素时触发观察者?

我不能使用滚动事件,因为我使用的是 CSS scroll-snap,这会导致浏览器吞下事件,然后 JS 才能检测到它。

wil*_*nco 2

希望我能够在这里抓住您的挑战,因此我将尝试提出一个适合您的用例的解决方案,即使没有代码可供参考。

根据我的理解,您使用的是scroll-snap在用户通过滚动进行交互时捕捉部分,您的目的是让交叉观察器在用户从一个部分移动到另一个部分时触发。

在下面的示例中,您将看到如何捕捉部分,但调试器会显示向用户显示哪个部分。

const debuggerSpan = document.querySelector('#current-section');
const sections = [...document.querySelectorAll('.scroll-snap-item')];
const div = document.querySelector('.scroll-snap-container');

/*
 * This method will get called any time a section touches the top
 * of the viewport.
 */
const intersectionDetected = (entries, observer) => {
  entries.forEach((entry) => {
    const {
      innerText
    } = entry.target;

    if (!entry.isIntersecting) return;

    // Making it obvious that the current section is correct.
    debuggerSpan.innerText = innerText;

  });
};

const observer = new IntersectionObserver(intersectionDetected, {

  /*
   * Root should be div and not the default (doc).
   */
  root: div,

  /*
   * Negative margin from the bottom creates an invisible line
   * to detect intersections.
   * 
   * The reason why the recommendation is to use -1% and -99% is to
   * avoid the race condition between two intersections happening
   * (AKA the section about to be out of the viewport and the section
   * about to enter the viewport).
   */
  rootMargin: '-1% 0% -99% 0%',

  /*
   * Default value but making it explicit as this is the 
   * only configuration that works.
   */
  threshold: 0 
});


sections.forEach(section => observer.observe(section));
Run Code Online (Sandbox Code Playgroud)
.scroll-snap-item {
  height: 100vh;
  display: grid;
  place-items: center;
  font-size: 4rem;
  scroll-snap-align: start;
}

.scroll-snap-container {
  scroll-snap-type: y mandatory;
  overflow-y: scroll;
  height: 100vh;
}


/* Decorative stuff below*/

.scroll-snap-item:nth-child(odd) {
  background-color: gray;
}

aside {
  position: fixed;
  font-size: 1.6rem;
  bottom: 16px;
  right: 16px;
  background-color: #333;
  color: white;
  padding: 16px;
  border-radius: 32px;
}
Run Code Online (Sandbox Code Playgroud)
<div class="scroll-snap-container">
  <section class="scroll-snap-item">1</section>
  <section class="scroll-snap-item">2</section>
  <section class="scroll-snap-item">3</section>
  <section class="scroll-snap-item">4</section>
  <section class="scroll-snap-item">5</section>
  <section class="scroll-snap-item">6</section>
</div>

<aside>Current section: <span id="current-section"></span></aside>
Run Code Online (Sandbox Code Playgroud)

我写了几篇实用的文章,涵盖了这一切背后的原因以及解决这种情况的思维过程。如果事情不够清楚,请随时阅读并发表评论:

这两本书都可以快速阅读,并且应该提供您使用 Intersection Observer 解决这个问题甚至更复杂问题所需的一切。另外,请随意使用我编写的名为The Intersection Observer Playground 的工具,您可以在其中尝试不同的配置并查看它们如何影响交叉点触发器。

希望这有帮助!