交叉路口观察员-突出显示当前路段

时间:2018-12-12 16:01:15

标签: navbar viewport highlight sections intersection-observer

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

似乎该部分需要先在100%范围之外,然后再重新显示,以使该类激活或停用(我相信这是因为我们正在检查entry.isIntersecting是否为真并且首先需要将其更改为false)。但是,这会导致不良行为。

我尝试摆弄if语句来检查entry.intersectionRatio,但我似乎也无法使其正常工作。为了以防万一,我也尝试在不同的浏览器中使用,但行为仍然相同。

我该如何解决?

这是一些code,显示了这种“越野车”行为。看起来像这样:

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

codepen来自this文章。

谢谢。

2 个答案:

答案 0 :(得分:0)

我一直在使用您的CodePen,并找到了解决此问题的方法。

主要思想是确保在root中只能同时有一个元素。为此,您需要做两件事:

首先,rootMargin的高度应尽可能薄。

rootMargin: '-45% 0px -55%'

我不确定那是否有效...一种更正确的方法是:

var vh = document.documentElement.clientHeight;
var topMargin = Math.ceil(-0.45*vh);
var botMargin = Math.ceil(-0.55*vh);
...
rootMargin: topMargin + "px 0px " + botMargin + "px";

第二件事是为.screen CSS类添加边距。

  margin-top: 3px;

(1或2像素可能太小)

该代码在Firefox和Chrome上正常运行,但在似乎未实现InstersectionObserver API的Safari上无法正常工作。我没有Windows,所以无法测试Edge和IE。

答案 1 :(得分:0)

您必须在观察者选项中明确定义根目录,因为演示程序在iframe中运行,否则rootMargin会被忽略。然后使用rootMargin使观察者的身高尽可能小。

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