Navbar 交叉点观察者-高亮显示当前部分

Navbar 交叉点观察者-高亮显示当前部分,navbar,viewport,highlight,sections,intersection-observer,Navbar,Viewport,Highlight,Sections,Intersection Observer,每当一个部分部分处于视图中或部分处于视图外时,我尝试激活和停用导航栏项目的类。如果我完全向下或向上滚动页面,代码工作正常。问题是如果我在一个部分的中间改变方向, 似乎该部分需要首先100%离开视图,然后再回到视图中,以便类激活或停用(我认为这是因为我们正在检查条目。isIntersecting是否为真,并且首先需要将其更改为假)。尽管如此,这还是会导致不必要的行为 我尝试过摆弄if语句来检查条目.intersectionRatio,但我似乎也无法让它工作。我也尝试过不同的浏览器,以防万一,但行为

每当一个部分部分处于视图中或部分处于视图外时,我尝试激活和停用导航栏项目的类。如果我完全向下或向上滚动页面,代码工作正常。问题是如果我在一个部分的中间改变方向,

似乎该部分需要首先100%离开视图,然后再回到视图中,以便类激活或停用(我认为这是因为我们正在检查
条目。isIntersecting
是否为真,并且首先需要将其更改为假)。尽管如此,这还是会导致不必要的行为

我尝试过摆弄if语句来检查
条目.intersectionRatio
,但我似乎也无法让它工作。我也尝试过不同的浏览器,以防万一,但行为还是一样的

我该怎么做

下面是一些显示这种“马车”行为的例子。看起来是这样的:

const sections = document.querySelectorAll('div.screen');
const config = {
  rootMargin: '-50px 0px -55%'
};

let observer = new IntersectionObserver(function (entries, self) {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      intersectionHandler(entry); 
    }
  });
}, config);

sections.forEach(section => {
  observer.observe(section);
});

function intersectionHandler(entry) {
  const id = entry.target.id;
  const currentlyActive = document.querySelector('nav li.active');
  const shouldBeActive = document.querySelector('nav li[data-ref=' + id + ']');

  if (currentlyActive) {
    currentlyActive.classList.remove('active');
  }
  if (shouldBeActive) {
    shouldBeActive.classList.add('active');
  }
}
代码笔来自文章


提前感谢。

我一直在使用你的密码笔,并找到了解决问题的方法

其主要思想是确保同一时间只有一个元素可以在
根中。要实现这一目标,您需要做两件事:

首先,
rootMargin
高度应尽可能薄

rootMargin: '-45% 0px -55%'
第二件事是为
.screen
CSS类添加边距

  margin-top: 3px;
(1或2像素可能太小)


该代码在Firefox和Chrome上运行良好,但在Safari上不起作用,因为Safari似乎没有实现InsterSectionObserverAPI。我没有Windows,因此无法测试Edge和IE。

您必须在observer选项中明确定义根,因为您的演示在iframe中运行,否则将忽略根边距。然后使用
rootMargin
使观察者的高度尽可能小

const config = { 
   root: document,
   rootMargin: '-50% 0 -50%'
}