[React] Framer-Motion으로 슬라이드 만들기(기본편)
Framer-Motion
공식 홈페이지: https://www.framer.com/motion/
리액트용 모션 라이브러리입니다.
이것저것 세련된 애니메이션 효과들을 쉽게 사용할 수 있습니다.
설치
npm install framer-motion
Import
import { motion } from "framer-motion"
기본 사용방법
motion이 들어갈 요소를 지정하기
HTML, SVG 요소에 motion
을 붙여줍니다.
<motion.div animate={{ scale: 0.5 }} />
styled-component를 사용하는 경우에는 styled(motion.html요소)
로 작성합니다.
const Box = styled(motion.div)`...`;
애니메이션 만들기
motion
컴포넌트의 prop을 넣어서 애니메이션을 적용합니다. (prop 값은 맘대로 정해도됨)initial
: 애니메이션이 들어가기 전 초기상태animate
: 애니메이션 효과variants
:initial
과animate
의 상태를 정리해놓은 오브젝트입니다.
https://www.framer.com/docs/transition/ 로 가면 다양한 애니메이션 효과들이 있습니다.
const variants = {
hidden: { opacity: 0 },
visible: { opacity: 1 },
}
return (
<motion.div
initial="hidden"
animate="visible"
variants={variants}
/>
)
슬라이드를 만들자
임시 이미지를 넣은 데모 버전입니다. 전체 코드는 여기서 봐주세요❤
컴포넌트의 구조
- 실질적으로 슬라이드를 담당하는 Box 컴포넌트가 1개밖에 들어있지 않습니다.
AnimatePresence
를 이용하여 슬라이드를 만듭니다.
import { AnimatePresence, motion } from "framer-motion";
import 해주세요!custom
prop을 이용하여 슬라이드 애니메이션의 방향을 바꿉니다.
<Wrapper>
<SlideWrap>
<AnimatePresence custom={back}>
<Box
custom={back}
variants={boxVariants}
src={images[imageIndex]}
initial="entry"
animate="center"
exit="exit"
key={visible}
/>
</AnimatePresence>
</SlideWrap>
<button onClick={prevPlease}>prev</button>
<button onClick={nextPlease}>next</button>
</Wrapper>
- 사진 데이터들은 따로
image-data.js
파일을 만들어서 이미지 주소들을 정리했습니다.
export const images = [
"https://via.placeholder.com/250x250?text=1",
"https://via.placeholder.com/250x250?text=2",
"https://via.placeholder.com/250x250?text=3"
];
💙AnimatePresence
- 자식 요소가 React 트리에서 제거될 때 애니메이션도 같이 제거해주는 컴포넌트입니다.
- 즉, 요소를 애니메이션 효과와 함께 깔끔하게 퇴장시킬 수 있는 기능을 갖고 있습니다.
- 기본
motion
과는 달리 종료 애니메이션exit
를 작성해야합니다.
슬라이드 박스에 데이터 넣기
- 일단
custom
prop을 지정하지 않고 작성했습니다. - 박스가 1개 밖에 없으므로 슬라이드를 구분하기 위해 key 값을 넣습니다.
- visible은 버튼을 누를 때마다 1씩 증가 혹은 감소합니다.
- popmotion의 wrap을 사용하여 박스마다 이미지를 적용합니다.
wrap(min:number, max:number, v:number)
wrap은 정의된 숫자 범위를 넘어서면 숫자를 다시 처음 상태로 바꿉니다.
import { wrap } from "popmotion";
const [visible, setVisible] = useState(0);
//박스마다 이미지 적용
const imageIndex = wrap(0, images.length, visible);
...
<Box
variants={boxVariants}
src={images[imageIndex]}
initial="entry"
animate="center"
exit="exit"
key={visible}
/>
버튼 만들기
- 일단
custom
prop을 지정하지 않고 작성했습니다.
const nextPlease = () => {
setVisible((prev) =>
prev === images.length - 1 ? images.length - 1 : prev + 1
);
};
const prevPlease = () => {
setVisible((prev) => (prev === 0 ? 0 : prev - 1));
};
<button onClick={prevPlease}>prev</button>
<button onClick={nextPlease}>next</button>
애니메이션 variants 작성하기
- 일단
custom
prop을 지정하지 않고 작성했습니다.
const boxVariants = {
//등장 애니메이션 (애니메이션 진행률:0%)
entry:{
x: 500,
opacity: 0,
scale: 0
},
//메인 애니메이션 (50%, 슬라이드가 가운데로 왔을 때의 상태)
center: {
opacity: 1,
x: 0,
scale: 1,
transition: { duration: 0.5 }
},
//종료 애니메이션 (100%)
exit:{
x: -500,
opacity: 0,
scale: 0,
transition: { duration: 0.5 }
}
};
중간체크!
next 버튼을 누를 때 오=>왼으로 잘 넘어가서 보기 좋은데
prev 버튼을 누르면 어딘가 어색해보입니다.
<AnimatePresence>
의 custom
prop을 이용해 prev 버튼을 눌렀을 때의 애니메이션 방향을 바꿔보겠습니다.
💜custom prop을 이용하여 애니메이션에 변주를 주기
useState
를 이용하여 방향의 상태를 정합니다.
//방향 상태
const [back, setBack] = useState(false);
//next 버튼
const nextPlease = () => {
//next 때는 false
setBack(false);
setVisible((prev) =>
prev === images.length - 1 ? images.length - 1 : prev + 1
);
};
//prev 버튼
const prevPlease = () => {
//prev 때는 true
setBack(true);
setVisible((prev) => (prev === 0 ? 0 : prev - 1));
};
- variants에 back을 인자로 받아 조건에 따른 애니메이션을 작성합니다.
(back)=>({...})
블록 괄호로 감싸주는 거 잊지 않기!
const boxVariants = {
entry: (back: boolean) => ({
//back일 때(prev 버튼을 눌렀을 때) 반대방향으로
x: back ? -500 : 500,
opacity: 0,
scale: 0
}),
center: {
opacity: 1,
x: 0,
scale: 1,
transition: { duration: 0.5 }
},
exit: (back: boolean) => ({
//back일 때(prev 버튼을 눌렀을 때) 반대방향으로
x: back ? 500 : -500,
opacity: 0,
scale: 0,
transition: { duration: 0.5 }
})
};
<AnimatePresence>
와 자식 요소에도custom
prop을 추가합니다.
<AnimatePresence custom={back}>
<Box
custom={back}
variants={boxVariants}
src={images[imageIndex]}
initial="entry"
animate="center"
exit="exit"
key={visible}
/>
</AnimatePresence>
끝입니다!! 참 쉽죠?
응용편(예고)
다음 포스트는 응용편으로 무한 슬라이드 + 모바일 해상도 한정 스와이퍼에 대해 작성하겠습니다.
코로나때문에 몸상태가 메롱이라서 한꺼번에 못쓰겟네요...ㅠㅠㅠ
응용편에 보여드릴 슬라이드입니다. 넷플릭스 클론인데 강의 내용 외에 몇몇 기능들을 추가했습니다.
📎참고
framer-motion 공식 홈페이지 - https://www.framer.com/motion/
슬라이드 예제 - https://codesandbox.io/s/pqvx3
wrap - popmotion - https://popmotion.io/popcorn/api/wrap/
React JS 마스터클래스 - 노마드코더 https://nomadcoders.co/react-masterclass
Author And Source
이 문제에 관하여([React] Framer-Motion으로 슬라이드 만들기(기본편)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@soonmac/Framer-Motion으로-슬라이드-만들기기본편저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)