스크롤 할 때마다 네비게이션 버튼 선택하기

GY·2021년 10월 25일
0

Website

목록 보기
3/3
post-thumbnail

navbar 의 메뉴버튼과 각 섹션들이 연결되어야 한다.
스크롤하면서 화면에 들어오는 섹션에 해당하는 메뉴 버튼이 선택되어야 한다.

section별 id 배열 만들기

HTML : section

아래와 같이 각 섹션 별로 id가 지정되어 있다.

 <section class="skills" id="skills">

section id array

지정된 섹션별 id를 넣은 section id 배열을 만든다.

const sectionIds = [
  '#profile',
  '#about-me',
  '#skills',
  '#my-work',
  '#contact',
]

HTML : navBar

dataset으로 nav바의 메뉴버튼별로 각각의 section id와 동일한 data-link를 지정해주었다.

    <div class="menu menu-spread">
      <span class="menu--home menu-selected" data-link="#profile">home</span>
      <span class="menu--about" data-link="#about-me">about</span>
      <span class="menu--skills" data-link="#skills">skills</span>
      <span class="menu--my-work" data-link="#my-work">my work</span>
      <span class="menu--contact" data-link="#contact">contact</span>
    </div>

querySelector

const sections = sectionIds.map(id => document.querySelector(id));
const navItems = sectionIds.map(id =>
  document.querySelector(`[data-li nk="${id}"]`)
);

intersectionObvserver

let options = {
  root: null,
  rootMargin: '0px',
  threshold: 0.3,
}

let observer = new IntersectionObserver(callback, options);
sections.forEach(section => observer.observe(section));

각 섹션별로 intersectionObserver를 부착했다.

intersectionObserver - callback function

맨 첫번째 섹션과 마지막 섹션이 문제였다.
맨 첫번째 섹션은 이미 처음 페이지가 로드되었을 때 화면안에 들어있기 때문에 intersecting이 0이다.
맨 마지막 섹션은 ....
그래서 한 섹션이 지나갈 때마다 변수로 지정한 인덱스를 +1 해주고, 그 인덱스 별로 메뉴버튼이 선택되도록 해야 한다.

let callback = (entries, observer) => {
  entries.forEach(entry => {
    if(!entry.isIntersecting && entry.intersectionRatio > 0){
      const index = sectionIds.indexOf(`#${entry.target.id}`);
      if (entry.boundingClientRect.y < 0) {
        selectedNavIndex = index + 1;
      } else {
        selectedNavIndex = index - 1;
      }
    }
  });
};

이 경우 첫번째와 마지막 섹션은 카운트 되지 않는다.
index의 초기값을 지정해주자.
index값은 처음에 0부터 시작할 것이기 때문에 전역변수로 0으로 지정해준다.
let selectedNavIndex = 0;

index of first & last section

window.addEventListener('wheel', () => {
  selectNavItem(navItems[selectedNavIndex]);//다음 부분 참고
  if(window.scrollY === 0) {
    selectedNavIndex = 0;
  } else if (window.scrollY + window.innerHeight
      === document.body.clientHeight) {
    selectedNavIndex = navItems.length - 1;
  }
})

window.scrollY가 0일때, 즉 맨 첫번째 섹션일 때는 index의 값을 0으로 지정해준다.
마지막섹션일 때는 navItems.length-1 즉 전체 섹션 중 마지막 값으로 지정해준다.

classList.add & remove()

let selectedNavItem = navItems[0];

function selectNavItem(selected) {
  selectedNavItem.classList.remove('menu-selected');
  selectedNavItem = selected;
  selectedNavItem.classList.add('menu-selected');
}
profile
Why?에서 시작해 How를 찾는 과정을 좋아합니다. 그 고민과 성장의 과정을 꾸준히 기록하고자 합니다.

0개의 댓글