【问题标题】:Trigger IntersectionObserver when element is already in viewport当元素已经在视口中时触发 IntersectionObserver
【发布时间】:2019-09-15 16:26:03
【问题描述】:

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

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

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

我无法使用滚动事件,因为我使用的是 CSS scroll-snap,这会导致事件在 JS 检测到之前被浏览器吞噬。

【问题讨论】:

  • 我遇到了类似的无限表滚动问题。在上一页和下一页的表格之前和之后我都有观察员。问题是一旦观察者可见,回调就不再触发。我想出的笨拙的解决方案是向上或向下滚动 1px - 视情况而定,从而迫使观察者回调在滚动时再次触发。

标签: javascript intersection-observer


【解决方案1】:

希望我能够理解您的问题,因此我将尝试提出一个适合您的用例的解决方案,即使没有可用作参考的代码。

据我了解,您正在使用scroll-snap 在用户通过滚动进行交互时捕捉部分,您的目的是让 Intersection Observer 在用户从一个部分移动到另一个部分时触发。

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

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));
.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;
}
<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>

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

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

希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    • 2014-06-06
    • 1970-01-01
    • 2014-12-08
    • 2020-06-19
    • 1970-01-01
    • 2021-05-06
    相关资源
    最近更新 更多