navbar 의 메뉴버튼과 각 섹션들이 연결되어야 한다.
스크롤하면서 화면에 들어오는 섹션에 해당하는 메뉴 버튼이 선택되어야 한다.
아래와 같이 각 섹션 별로 id가 지정되어 있다.
<section class="skills" id="skills">
지정된 섹션별 id를 넣은 section id 배열을 만든다.
const sectionIds = [
'#profile',
'#about-me',
'#skills',
'#my-work',
'#contact',
]
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>
const sections = sectionIds.map(id => document.querySelector(id));
const navItems = sectionIds.map(id =>
document.querySelector(`[data-li nk="${id}"]`)
);
let options = {
root: null,
rootMargin: '0px',
threshold: 0.3,
}
let observer = new IntersectionObserver(callback, options);
sections.forEach(section => observer.observe(section));
각 섹션별로 intersectionObserver를 부착했다.
맨 첫번째 섹션과 마지막 섹션이 문제였다.
맨 첫번째 섹션은 이미 처음 페이지가 로드되었을 때 화면안에 들어있기 때문에 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;
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 즉 전체 섹션 중 마지막 값으로 지정해준다.
let selectedNavItem = navItems[0];
function selectNavItem(selected) {
selectedNavItem.classList.remove('menu-selected');
selectedNavItem = selected;
selectedNavItem.classList.add('menu-selected');
}