[React] IntersectionObserver를 사용하여 스크롤 애니메이션 구현하기
본문 바로가기
더 알아보기/기능

[React] IntersectionObserver를 사용하여 스크롤 애니메이션 구현하기

by 은돌1113 2022. 11. 4.
 

[JS] IntersectionObserver 사용해보기

코딩 애플 영상은 짧지만 임팩트 있게 머리에 콕콕 박아줘서 너무 좋은 것 같다. IntersectionObserver 기능으로 스크롤 애니메이션을 쉽게 만들 수 있다고 해서 따라 해 보았다. (반응형 웹사이트 구

eundol1113.tistory.com

앞 글에서 정리했던 JS에 IntersectionObserver 기능을 React에 적용 해보았다.

React에 Intersection Observer API가 있다는 데 봐도 어떻게 사용하는 건지 잘 모르겠어서 JS와 useRef를 섞어서 구현해보았다.

 

  const introRef = useRef(null);
  const guideRef = useRef(null);

  useEffect(() => {
    let introObserver = new IntersectionObserver((e) => {
      // e : 현재 감시 중인 모든 div 박스가 출력됨
      e.forEach((box) => {
        // 감시 중인 box가 등장 & 퇴장 시 실행됨 => 이중으로 동작함

        // 화면에 보일 때만 style을 변경하고 싶을 때는
        if (box.isIntersecting) {
          box.target.style.opacity = 1;

          // intro 자식 중에 한 부분을 선택해서 또다른 intersectionObserver 연결함
          if (e[0].target.className === "content_6") {
            Array.prototype.forEach.call(guideRef.current.children, (child) => {
              // .observe() : HTML 요소가 화면에 등장하는 지 감시해 주는 역할
              // 파라미터에 HTML 요소를 넣어주면 된다.
              guideObserver.observe(child);
            });
          }
        } else {
          box.target.style.opacity = 0;
        }
      });
    });

    let guideObserver = new IntersectionObserver((e) => {
      e.forEach((box2) => {
        if (box2.isIntersecting) {
          box2.target.style.background = "#f2f4f6 0% 0% no-repeat padding-box";
        } else {
          box2.target.style.background = "white";
        }
      });
    });

    Array.prototype.forEach.call(introRef.current.children, (child) => {
      introObserver.observe(child);
    });
  }, []);

 

 

이중 IntersectionObserver 사용한 이유

introObserver는 소개 페이지 안에서에 스크롤 애니메이션이고,

guideObserver는 소개 페이지 중에서도 특정 가이드 부분에 스크롤 애니메이션을 넣은 코드이다.

 

그래서 introObserver 콜백 함수 안에 if문을 넣어서 content_6(특정 부분)일 때 guideObserver.oberserve()를 실하도록 설정했다.

 

Array.prototype.forEach.call(ref, () => {});를 사용한 이유

ref.current.children을 콘솔로 찍어보면 HTMLCollection으로 출력되는 걸 볼 수 있는 데 HTMLCollection은 filter, forEach와 같은 Array 함수 기능을 제공하지 않기 때문에 Array.prototype에 바인딩하여 자식들을 출력하였다.

(아래 사이트 참고함)

 

[JavaScript_error] 01. HTMLCollection는 forEach, filter 등을 사용 불가.

🟡 HTMLCollection는 forEach, filter 등을 사용 불가. - JS로 HTML 요소를 불러오고 싶을 때 document.getElementsBy~~ 함수를 사용해서 가져올 것입니다. 이때 가져온 element들은 HTMLCollection객체 형태로 가져오는

daily-life-of-bigone.tistory.com

 

비교

intersectionObserver 적용 전
intersectionObserver 적용 후

 

+ 추가로 기존에 구현했던 window.addEventListener("scroll", handleScroll);도 intersectionObserver로 변경 해보았다.

 

위 예제와 다른 점이라면 "ref에 style을 변경하였는가", "state에 따라 className을 부여하여 style을 변경하였는가"일 것 같다.

(🥸 React는 document를 직접 건드리면 안되기 때문에 주로 state 값에 따라 className을 부여하여 style을 변경한다.)

  useEffect(() => {
    let footerObserver = new IntersectionObserver((e) => {
      e.forEach((box3) => {
        if (box3.isIntersecting) {
          setBottomState(false);
        } else {
          setBottomState(true);
        }
      });
    });

    Array.prototype.forEach.call(footerRef.current.children, (child) => {
      footerObserver.observe(child);
    });
  }, []);

 

사용 후기

뭔가 소개 페이지가 더 다이나믹 해지면서 공을 들인 느낌이 나는 것 같다. 다음에는 intersectionObserver를 사용하여 무한 스크롤 기능도 만들어 봐야겠다. 기능 공부는 아주 즐거워☺️

댓글