스크롤스파이 만들기

keon lee·2025년 1월 31일

Javascript

목록 보기
1/1
post-thumbnail

오늘은 스크롤스파이를 Jquery를 사용해서 만들어보았다.

HTML

<!-- 네비게이션 영역 -->
<nav class="snb">
    <ol class="snb__list">
        <li class="snb__item snb__item--active">
            <a href="#" role="button" class="snb__link"><span class="snb__txt">2024</span></a>
        </li>
        <li class="snb__item">
            <a href="#" role="button" class="snb__link"><span class="snb__txt">2023</span></a>
        </li>
        <li class="snb__item">
            <a href="#" role="button" class="snb__link"><span class="snb__txt">2022</span></a>
        </li>
    </ol>
</nav>
<!-- 네비게이션 컨텐츠 영역 -->
<li id="year2024" class="sc-work__item">  <!-- 위치 찾기용 ID -->
    <a href="#" target="_blank" class="work-card">
        <div class="work-card__title-area">
            <strong class="work-card__title">lamiche</strong>
            <p class="work-card__desc">swiper를 사용하여 제작한 신규 홈페이지입니다.</p>
        </div>
    </a>
    <a href="#" class="sc-work__tag--review tag--review">code reivew</a>
</li>

... 생략 ...

HTML은 일반 네비게이션과 컨텐츠 영역처럼 잡고, 컨텐츠 리스트 중 특정 컨텐츠의 위치로 이동해야해서 구분하기 편하게 ID를 부여하였다.

스크립트

스크립트는 크게 스크롤 이벤트, 클릭 이벤트 두 가지가 필요하였다.

1. 변수

let flag = false; // 클릭하여 이동하는 동안 스크롤 이벤트 막기 위한 flag 변수 설정

const $workNavItem = $('.snb__item');
const $workItem = $('.sc-work__item[id]');

let workNavPadding = Math.abs($('.sc-work__right').offset().top - $('.sc-work__list').offset().top); 

// 타겟 offset top 값 배열로 저장
let workItemPosY = $workItem.map((idx, item) => {
	return ($(item).offset().top - workNavPadding).toFixed(0);
}).get();

2. 스크롤 이벤트

$(window).on('scroll', () => {
    if (flag) return; // 클릭 애니메이션 중 작동 X
    let wTop = $(window).scrollTop().toFixed(0);
  
    // 성능을 위해서 each문 대신 for문 사용 
    for (let i = 0; i < workItemPosY.length; i++) {
        if (wTop >= workItemPosY[i] - 1) { // 스크롤이 타겟 offset().top 보다 높으면
            $workNavItem.eq(i).addClass("snb__item--active").siblings().removeClass('snb__item--active');
        }
    }
})

스크롤 이벤트는 workItemPosY에 담긴 값보다 스크롤이 높을 시 클래스를 부여하였다.
오차가 있어서 toFixed()를 사용했고, 아직 - 1을 해야 해당 요소로 이동했을 때 네비게이션에 active가 맞게 작동하는데 이유는 더 고민해봐야겠다...

3. 클릭 이벤트

$workNavItem.on('click', function(e) {
    flag = true;
    e.preventDefault();

    let navIdx = $(this).index();

    if ($workItem.length) {
        $(this).addClass('snb__item--active').siblings().removeClass('snb__item--active');
        $('html, body').animate({ scrollTop: workItemPosY[navIdx] }, 300, function() {
            flag = false; // 애니메이션 종료 시 flag false로 변환
        });
    } else {
        flag = false;
    }
});

클릭하여 이동하는 애니메이션은 Jquery animate로 만들었다.
처음에 html, body를 선택자로 잡아야하는 이유가 궁금했는데,
JS에선 window를 잡아서 사용하지만, Jquery 사용 시 html, body를 사용해야 스크롤 이동이 가능하다고 한다.

0개의 댓글