본문 바로가기
Js

원페이지 스크롤

by 영감은어디에 2025. 3. 3.

<nav>
<a href="#section1" class="active">섹션 1</a>
<a href="#section2">섹션 2</a>
<a href="#section3">섹션 3</a>
<a href="#section4">섹션 4</a>
<a href="#section5">섹션 5</a>
</nav>

<section id="section1" style="height: 100vh; background: lightgray;">섹션 1</section>
<section id="section2" style="height: 100vh; background: lightblue;">섹션 2</section>
<section id="section3" style="height: 100vh; background: lightgreen;">섹션 3</section>
<section id="section4" style="height: 100vh; background: lightcoral;">섹션 4</section>
<section id="section5" style="height: 100vh; background: lightsalmon;">섹션 5</section>
const navLinks = document.querySelectorAll("nav a");
const sections = document.querySelectorAll("section");

// 네비게이션 클릭 시 부드러운 스크롤
navLinks.forEach(link => {
link.addEventListener("click", function(event) {
    event.preventDefault();

    // 스크롤 애니메이션 중 active 업데이트 방지
    isScrolling = true;

    // 모든 네비게이션에서 active 제거 후 클릭된 요소에 active 추가
    navLinks.forEach(a => a.classList.remove("active"));
    this.classList.add("active");

    const targetId = this.getAttribute("href").substring(1);
    const target = document.getElementById(targetId);
    const offset = target.offsetTop;
    const startPosition = window.scrollY;
    const distance = offset - startPosition;
    const duration = 600;
    let startTime = null;

    function animation(currentTime) {
    if (startTime === null) startTime = currentTime;
    const timeElapsed = currentTime - startTime;
    const progress = Math.min(timeElapsed / duration, 1);
    const easing = progress < 0.5 ? 2 * progress ** 2 : 1 - Math.pow(-2 * progress + 2, 2) / 2;
    window.scrollTo(0, startPosition + distance * easing);

    if (timeElapsed < duration) {
        requestAnimationFrame(animation);
    } else {
        isScrolling = false; // 애니메이션 끝나면 다시 감지 시작
    }
    }

    requestAnimationFrame(animation);
});
});

let isScrolling = false;

// 스크롤 시 해당 섹션이 보이면 active 적용
function updateActiveNav() {
if (isScrolling) return; // 스크롤 애니메이션 중이면 감지 안 함

let scrollPosition = window.scrollY;

sections.forEach((section, index) => {
    const sectionTop = section.offsetTop;
    const sectionHeight = section.offsetHeight;

    // 화면 높이의 50%가 해당 섹션에 들어가면 active 처리
    if (scrollPosition >= sectionTop - sectionHeight / 2 && scrollPosition < sectionTop + sectionHeight / 2) {
    navLinks.forEach(a => a.classList.remove("active"));
    navLinks[index].classList.add("active");
    }
});
}

window.addEventListener("scroll", updateActiveNav);

'Js' 카테고리의 다른 글

wow.js animate  (0) 2025.03.09
rotate, mouse move, delay  (0) 2025.03.07
circle, strokeDashoffset, scrollTop, 그래프  (0) 2025.03.06
gsap, mouse move  (0) 2025.03.05
menu bar mouse move  (0) 2025.02.25
폴리곤. 컬러 로테이션 hue-rotate  (0) 2025.02.24
createElement, mouse move  (0) 2025.02.23
Lottie json 파일 단순 마우스 오버 효과  (0) 2024.10.17