리액트 라이브러리 중 framer motion이라는 라이브러리가 있다. 화면에서 다양한 애니메이션을 만들기 위해서 쌩으로 css와 스크립트를 짜서 구현하려면 복잡하다. 그러나 framer motion만 있다면 간단하게 구현이 가능하다. 이걸로 다양한 애니메이션을 구현할 수 있는데 그 중에서 우선 나는 스크롤을 할때 화면에서 글자가 점점 나타나도록 구현해 보도록 하겠다.
1. 설치하기
npm을 통해 먼저 라이브러리를 설치해준다.
npm i framer-motion
아래는 공식문서이며 어떻게 사용하는지 볼 수 있다.
https://www.framer.com/motion/
Documentation | Framer for Developers
An open source, production-ready motion library for React on the web.
www.framer.com
2. 애니메이션 설정하기
먼저 테스트 할 컴포넌트를 하나 만들어 준다. 필자의 경우 Scroll.tsx 파일을 하나 생성하였다.
그런다음 framer-motion 라이브러리를 가져와 사용하도록한다.
import { motion } from 'framer-motion'
스크롤을 테스트 하기 위해서 박스를 하나 만든다. css는 tailwind를 사용하여 간단하게 만들었다.
const Scroll = () => {
return (
<>
<div className='flex items-center justify-center h-screen '>
<div className='bg-indigo-800 text-white font-bold rounded-lg border shadow-lg p-10'>
1번 항목
</div>
</div>
<div className='flex items-center justify-center h-screen'>
<div className='bg-indigo-800 text-white font-bold rounded-lg border shadow-lg p-10'>
2번 항목
</div>
</div>
</>
)
}
export default Scroll
그런 다음 이제 motion 컴포넌트를 활용할 차례이다. motion 컴포넌트에는 다양한 prop들이 존재하는데 간단하게 살펴보면 애니메이션 시작 전 상태를 설정하고, 애니메이션이 끝났을때의 모습 그리고 애니메이션 변화 과정(transition)을 설정하여 원하는 애니메이션을 만들 수 있다. 아래의 코드를 한번 보도록 하자
<motion.div
initial={{ opacity: 0, y: 50 }} //애니메이션 시작전
whileInView={{ opacity: 1, y: 0 }} //스크롤하여 애니메이션이 끝난 모습
viewport={{ once: false }} //뷰포트 설정
transition={{ //트랜지션 설정
ease: 'easeInOut',
duration: 2,
y: { duration: 1 },
}}
>
여기서 초기에 opacity 즉 투명도를 0으로 주고 스크롤 할때 투명도를 1로하여 완전히 보이도록 설정하였다. 그리고 추가로 아래에서 위로 나타나도록 하기위해 y축 값을 50에서 0으로 가도록 설정하였다.
viewport의 경우 우리가 화면에 안보였다가 다시 보일때 애니메이션을 재동작 할 건지 여부이다. 여기서는 false로 주었다. false로 주게 된다면 우리가 설정한 모션 영역이 안보일때 다시 그영역으로 돌아가면 애니메이션이 실행 된다.
다음으로 transition이다. 애니메이션이 변화할때의 속도 즉 우리가 영상을 제작할때 페이드인 페이드아웃과 비슷한 개념이다. ease와 duration 값을 각각 줄 수 있다.
저렇게 만든 motion.div 컴포넌트를 우리가 적용할 네모 박스에 적용하도록 하겠다.
아래는 최종 코드이다.
import { motion } from 'framer-motion'
const Scroll = () => {
return (
<>
<div className='flex items-center justify-center h-screen '>
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false }}
transition={{
ease: 'easeInOut',
duration: 2,
y: { duration: 1 },
}}
>
<div className='bg-indigo-800 text-white font-bold rounded-lg border shadow-lg p-10'>
1번 항목
</div>
</motion.div>
</div>
<div className='flex items-center justify-center h-screen'>
<motion.div
initial={{ opacity: 0, y: 50 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: false }}
transition={{
ease: 'easeInOut',
duration: 2,
y: { duration: 1 },
}}
>
<div className='bg-indigo-800 text-white font-bold rounded-lg border shadow-lg p-10'>
2번 항목
</div>
</motion.div>
</div>
</>
)
}
export default Scroll
여기서 실수로 네모 박스에만 motion.div로 감싸야 했는데 네모 박스의 부모 영역까지 전부 감싸서 이상하게 동작하였다... 아무튼 네모 박스만 감싸니 잘 동작하였다. 아래는 동작 화면이다.
'프론트엔드 개발 > React' 카테고리의 다른 글
[React] 리액트 + TS 에서 한글 타이핑 효과 구현하기(type-hangul) (2) | 2024.10.15 |
---|---|
[React] 카카오 지도 API 연동하기 (TS + Vite) (2) | 2024.09.02 |
[React] D-Day 계산하기 (typescript) (0) | 2024.08.28 |
[React] 갤러리 화면에서 이미지 모달창 기능 구현하기(Typescript) (0) | 2024.08.09 |
[React] 간단한 갤러리 화면 구현하기(Typescript) (0) | 2024.08.08 |