【问题标题】:Javascript - How to make a section 'active' when scrolled toJavascript - 滚动到时如何使部分“活动”
【发布时间】:2021-08-28 00:31:27
【问题描述】:

我对 JavaScript 很陌生,如果我的任何描述不够清晰,敬请见谅。

我已经建立了一个带有 java 脚本生成菜单的小型网站,我只是想添加功能以在滚动到菜单时突出显示菜单中的某个部分(并使“活动”)。我将以下内容放在一起,不会在控制台中引发任何错误,所以我不确定我错过了什么:

const sectionHead = document.querySelectorAll('h2');

const sections = document.querySelectorAll('section');
const nav = document.querySelector('nav');

// build the nav
function navMenu(){
  for(let section of sectionHead){
      let listItem = document.createElement("li");
      listItem.innerHTML = section.textContent;
      nav.appendChild(listItem);
      listItem.classList.add('menu__link');
      listItem.addEventListener("click", ()=>{
        section.scrollIntoView({behavior: "smooth"});
      });
  };
}
navMenu();

const nav_items = document.querySelectorAll('.menu__link')

window.addEventListener("scroll", () => {
  let current = "";
  sections.forEach((section) => {
    const sectionTop = section.offsetTop;
    const sectionHeight = section.clientHeight;
    if (pageYOffset >= sectionTop - sectionHeight / 3) {
      current = section.getAttribute("id");
    }
  });
//set section as active
  nav_items.forEach((li) => {
    li.classList.remove("your-active-class");
    section.classList.remove("your-active-class");
    if (section.classList.contains(current)) {
      section.classList.add("your-active-class");
      //console.log (li.classList);
    }
  });
});

“your-active-class”类有一些自定义 CSS 设置,因此它只会改变菜单中的可见性。

非常感谢任何帮助

【问题讨论】:

标签: javascript html function dom-events sections


【解决方案1】:

这是您观察 DOM 元素是否在视图中的方式,并对其应用/删除类名。如果您查看检查器,您会看到“活动”类在进入和退出视图时被添加/删除。

window.addEventListener("load", function() {
  //Query objects on document load
  const sections = document.querySelectorAll("section")
  console.log(`We have ${sections.length} sections`)
  
  // Create options for Observer:
  const options = {
    rootMargin: '100px 0px',
    threshold: [0.25, 0, 0.25, 0]
  }
  
  // Create instance of IO:
  let observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
      if (entry.intersectionRatio > 0) {
        entry.target.classList.add('active')
      } else {
        entry.target.classList.remove('active')
      }
    })
  }, options)
  
  // Iterate over each queried el, and add observer:
  sections.forEach(section => { 
    observer.observe(section)
  })
  
  
})
section {
  background-color: red;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  margin: 6rem auto;
  transition: all 300ms ease-in-out;
}

.active {
  background-color: rgba(0,255,0,0.3);
  transition: all 300ms ease-in-out;
}
<section><div>This is the first section</div></section>
<section><div>This is the second</div></section>
<section><div>This is the third</div></section>

【讨论】:

  • 嗨乔尔,这正是我想要的,我只遇到了两个问题——这段代码可以一次将多个部分设置为活动状态。其次,除了突出显示整个部分之外,如何使与该部分对应的菜单项突出显示?
  • 我明白了。这和我想的有点不同。交叉点观察者可以同时感知屏幕上的 许多 个实例。您始终可以根据它们的 intersectionRatio 评估它们,但我不确定您的特定用例是什么样的。您可以选择活动集的后代元素,或定位元素本身。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
  • 2011-03-19
  • 1970-01-01
  • 2020-11-07
  • 1970-01-01
相关资源
最近更新 更多