[js] 스크롤 애니메이션 구현

박용희·2023년 7월 18일
0

[js] 스크롤 애니메이션 구현

클론코딩 중, 스크롤 애니메이션이 있길레 구현해봤습니다.

스크롤 이벤트 리스너 생성

window.addEventListener("scroll", 함수명)

특정 요소 찾기

let introduceContainer = document.querySelector(".introduce-text-container");
let imgContainers = document.querySelectorAll(".img-container");

.querySelector : 지정된 선택자(selector)에 해당하는 첫 번째 요소를 반환
.querySelectorAll : 지정된 선택자(selector)에 해당하는 모든 요소를 NodeList라는 정적인 유사 배열 객체로 반환

스크롤 위치 ( 해당 div가 뷰포트에 보여지는지 확인 )

window.scrollY >= introduceContainer.offsetTop - window.innerHeight &&
window.scrollY <= introduceContainer.offsetTop + introduceContainer.offsetHeight

window.scrollY : 현재의 스크롤 위치, 맨 위에 위치했을 경우 0
.offsetTop : DOM 요소의 상단 경계(top edge)까지의 픽셀 거리를 나타내는 속성
.offsetHeight : DOM 요소의 전체 높이를 나타내는 속성

클래스 추가 및 삭제

imgContainer.classList.add("scroll-ani-class");
imgContainer.classList.remove("scroll-ani-class");

.classList.add : DOM 요소의 클래스(class) 목록에 새로운 클래스를 추가하는 메서드
.classList.remove : DOM 요소의 클래스(class) 목록에 새로운 클래스를 삭제하는 메서드

이벤트 리스너 삭제

window.removeEventListener("scroll", handleScroll);

시간 설정

setTimeout(function() {
  console.log("hello world");
}, 2000); // 2초 후에 콜백 함수 실행

만약 스크롤 이벤트를 한번만 작동할 것이라면, 애니메이션 시간에 맞춰 설정 후에 이벤트리스너를 삭제한다.
hover 애니메이션도 있을 경우, 애니메이션 class를 삭제하지 않으면 hover 애니메이션이 mouseleave일 때 추가한 애니메이션이 동작하는 경우가 있으므로 classList.remove를 이용해서 삭제를 할 수 있다.

해당 자바스크립트 전체 소스

function handleScroll() {
  let introduceContainer = document.querySelector(".introduce-text-container");
  let imgContainers = document.querySelectorAll(".img-container");

  let introduceContainerTop = introduceContainer.offsetTop;
  let introduceContainerHeight = introduceContainer.offsetHeight;

  let isAnimationAdded = false;

  imgContainers.forEach(function (imgContainer) {
    if (
      window.scrollY >= introduceContainerTop - window.innerHeight &&
      window.scrollY <= introduceContainerTop + introduceContainerHeight
    ) {
      imgContainer.classList.add("scroll-ani-class");
      isAnimationAdded = true;
    } else {
      imgContainer.classList.remove("scroll-ani-class");
    }
  });

  if (isAnimationAdded) {
    setTimeout(function () {
      imgContainers.forEach(function (imgContainer) {
        imgContainer.classList.remove("scroll-ani-class");
      });
    }, 1000);
      window.removeEventListener("scroll", handleScroll);
  }
}

window.addEventListener("scroll", handleScroll);

2개의 댓글

comment-user-thumbnail
2023년 7월 18일

정보가 많아서 도움이 많이 됐습니다.

답글 달기
comment-user-thumbnail
2023년 7월 18일

좋은 글 잘 읽었습니다, 감사합니다.

답글 달기