리액트로 스크롤 애니메이션 구현하기

Grace·2021년 11월 19일
6

코드캠프 TIL

목록 보기
15/34

우리가 javascript로 스크롤 애니메이션을 구현할 경우 getBoundingClientRect() 메서드를 많이 사용하게된다.

getBoundingClientRect() 메서드는 실제 element의 offset을 측정해주는데 이 메서드를 사용할 경우 메인스레드에서 실행되어 프로그램의 성능이 떨어진다.
이러한 문제를 보완하기위해서 나온 것이 intersection observer이다.

intersection observer는 callback과 option을 사용하여 비동기로 DOM 요소의 가시성을 측정해준다.

intersection observer를 사용해주기위해서 install을 해주자.
npm i react-intersection-observer

스크롤 애니메이션을 구현해보기 전에 먼저 알아야할 기본 지식들에 대해 간단하게 알아보고 가자

CSS

translate (x, y, z)

transitionProperty

transitionDuration

transitionTimingFunction

opacity

transform

Intersection - observer

threshold

타겟이 얼만큼 보여야 작동할지 결정해준다

observe()

disconnect()

React

useRef

DOM에서 특정 element를 가져올 때 사용한다.

useCallback(함수, [])

함수를 재사용하기위해 사용한다.

useEffect(함수, [])

컴포넌트 마운트, 언마운트, 업데이트 시 특정 작업을 처리한다.

나는 내가 만든 스크롤 애니메이션을 언제든지 가져와서 사용해줄 수 있도록 library에 컴포넌트 형식으로 만들어주었다.

import { useRef, useCallback, useEffect } from 'react'

// 스크롤하면 페이드인 하는 애니메이션
export const useScrollFadeIn = (direction, duration, delay) => {
// 해당 컴포넌트 가져오기
const element = useRef()
// direction 선택
const hanldeDirection = (name) => {
	switch (name) {
    	case "up":
        	return "translate3d(0, 50%, 0)"
        case "down": return "tranlate3d(0, -50%, 0)"
        case "left": return "translate3d(50%, 0, 0)"
        case "right": return "translate3d(-50%, 0, 0)"
        derault:
        return;
    }
}

// 설정해둔 컴포넌트를 만날때마다 함수가 재실행되도록 callback하기
const onScroll = useCallback(([entry])=>{
	const { current } = element
    if(entry.isIntersecting) {
    	current.style.tansitionProperty = 'all'
        current.style.transitionDuration = `${duration}s`
        current.style.transitionTimingFunction = "cubic-bezier(0, 0, 0.2, 1)"
        current.style.opacity = 1;
        current.style.tranform = "translate3d(0, 0, 0)"
    }
}, [delay, duration])

// intersection-observer로 컴포넌트 위치 observe하기
useEffect(()=>{
	let observer
    
    if(element.current) {
    	observer = new IntersectionObserver(onScroll, {threshold: 0.7})
        observer.observe(element.current)
        }
        
        return() => observer && observer.disconnect()
}, [onScroll])

return{ref: element, style: { opacity: 0, transform: handleDirection(direction) } }
}

귀찮으신 분들을 가져가서 그대로 사용하셔도 됩니다^___^

profile
기술블로그 이전:: https://meercat.tistory.com/

0개의 댓글