【问题标题】:IntersectionObserver does not work on small screens for long sections JSIntersectionObserver 不适用于长段 JS 的小屏幕
【发布时间】:2021-02-20 20:07:29
【问题描述】:

此脚本为活动部分发出活动类。最近注意到它停止在小屏幕上工作。即使在chrome的开发人员控制台中,我也会开始增加屏幕尺寸并且它会出现,一旦我开始减小它就会立即停止工作(活动类消失)。但只有一个较长的部分,在较短的部分中一切正常。如何解决这个问题?

在 sn-p 中,我设置了一个较大的固定高度,因此投资组合链接不会接收活动类,在我的示例中,当部分宽度增加时,它的高度会降低,所以在某些时候一切都开始工作了。

const links = document.querySelectorAll('.nav-link');
const sections = [... document.querySelectorAll('.forJS')];

const callback = (entries) => {
  links.forEach((link) => link.classList.remove('active'));
  const elem = entries.find((entry) => entry.isIntersecting);
  if (elem) {
    const index = sections.findIndex((section) => section === elem.target);
    links[index].classList.add('active');
  }
}

let observer = new IntersectionObserver(callback, {
  rootMargin: '0px',
  threshold: 0.5
});

sections.forEach((section) => observer.observe(section));
section {
  height: 100vh;
  scroll-y: auto;
}
.long{
height: 300vh;
}
.nav-link.active{
  color: red;
}
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<header class="fixed-top">
  <nav class="navbar navbar-expand-lg navCustom">
    <div class="container">

          <ul class="navbar-nav justify-content-center">
            <li class="nav-item">
              <a class="nav-link" href="#main">Main</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#about">About us</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#portfolio">Portfolio</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="#contacts">Contacts</a>
            </li>
          </ul>
    </div>
  </nav>
</header>

<section class="forJS text-center">Some info 1</section>
<section class="forJS text-center">Some info 2</section>
<section class="forJS text-center long">Some info 3</section>
<section class="text-center">Some info 4</section>
<section class="text-center">Some info 5</section>
<section class="text-center">Some info 6</section>
<section class="text-center">Some info 7</section>
<section class="text-center">Some info 8</section>
<section class="text-center">Some info 9</section>
<section class="forJS text-center">Some info 10</section>
</body>

【问题讨论】:

    标签: javascript ecmascript-6 intersection-observer


    【解决方案1】:

    主要问题是threshold: 0.5。这会告诉观察者在 50% 的元素在视口中可见时触发。对于您的“长”元素,由于它的高度为 300vh,并且您的视口高度为 100vh,因此它的最大可见度为 100vh/300vh = 33%,因此观察者永远不会触发。

    要解决这个问题,您可以将阈值调整为更小的值,例如 0.25。这将修复长部分的行为,但它会使您的较短部分的活动链接提前更改。所以我建议你添加 2 个观察者:1 个用于阈值为 0.5 (.forJS:not(.long)) 的短部分,另一个用于阈值为 0.25 (.forJS.long) 的较长部分。

    const links = document.querySelectorAll('.nav-link');
    const sectionsShort = [...document.querySelectorAll('.forJS:not(.long)')];
    const sectionsLong = [...document.querySelectorAll('.forJS.long')];
    const sections = [...document.querySelectorAll('.forJS')];
    
    const callback = entries => {
        links.forEach((link) => link.classList.remove('active'));
        const elem = entries.find((entry) => entry.isIntersecting);
        if (elem) {
            const index = sections.findIndex((section) => section === elem.target);
            links[index].classList.add('active');
        }
    }
    
    const observerShort = new IntersectionObserver(callback, {
        rootMargin: '0px',
        threshold: .5,
    });
    const observerLong = new IntersectionObserver(callback, {
        rootMargin: '0px',
        threshold: .25,
    });
    sectionsShort.forEach((section) => {
        observerShort.observe(section)
    });
    sectionsLong.forEach((section) => {
        observerLong.observe(section)
    });
    

    【讨论】:

    • 感谢您的回答!有一个不使用 InsertsectionObserver 的更简单的脚本,它的作用都是一样的。但底线是,例如,当用户不在“投资组合”部分时,投资组合链接不应该处于活动状态,对吧?在您的情况下,始终是上一个活动部分的活动链接。
    • 这个脚本和你的例子完全一样:stackoverflow.com/questions/66166602/…
    • @vcxbgfx 我不确定这是否是预期的行为。查看答案的更新,活动链接保持原样
    • @vcxbgfx 它以不同的方式进行。使用IntersectionObserver 是比您链接的其他答案更好的方法,因为它是专门为此用例设计的,而滚动事件需要侦听页面上的任何滚动并涉及手动检查滚动偏移和元素偏移量
    • 一切正常,但是这两段代码有一点冲突。重新加载页面或更新页面后,活动类消失,即使我们在活动区域​​。如果您删除其中一个,一切正常。在执行它们之前可能需要某种检查? sectionsShort.forEach((section) =&gt; {observerShort.observe(section)}); sectionsLong.forEach((section) =&gt; {observerLong.observe(section)});
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2019-01-04
    • 1970-01-01
    • 2021-12-17
    • 2013-06-30
    相关资源
    最近更新 更多