-
[Framer Motion] animation의 최강자 Framer Motion 알아보기, Animation/Variants/Gestures/Drag프론트엔드 개발자가 될거야./라이브러리 2023. 1. 8. 20:11
Framer Motion는 Framer가 제공하는 리액트용 애니메이션 라이브러리이다.
Framer Motion을 잘 이용한다면 Drag이벤트, Scroll이벤트 등 다양한 애니메이션들을 쉽게 표현해 낼 수 있다.
노마드코더 리액트 마스터를 통해 접할 수 있었는데
CSS로 했었으면 코드를 몇시간동안 고민고민해서 써야지 구현되는 효과들이
단 한줄로 구현되는 것을 보고 정말 놀라웠다...
아래는 Framer Motion 사이트이다. 여러 docs들도 있으니 보고 참고해도 좋을 것 같다.
https://www.framer.com/motion/
<다운로드 및 간단한 사용법>
다운로드는 다른 라이브러리와 똑같이
npm i framer-motion
하면 되고
framer-motion으로 애니메이션을 하길 원한다면
<motion.div> aaaaa </motion.div> <motion.span> bbbbb </motion.span>
이처럼 motion 패키지로부터 나와야 한다.
styled-component와 쓰고싶다면
const Box = styled(motion.div)` width: 200px; height: 200px; background-color: white; border-radius: 10px; box-shadow: 0 2px 3px rgba(0, 0, 0, 0.1), 0 10px 20px rgba(0, 0, 0, 0.06); `;
이처럼 괄호안에서 써서 사용하면 된다.
그리고 return문 안에서 적절한 곳에 Prop을 집어넣으면 된다!
function App() { return ( <Wrapper> <Box transition={{ duration: 3 }} animate={{ borderRadius: "100px" }} /> </Wrapper> ); }
<Animation>
위 영상처럼 처음에는 엄청 작다가 점점 커지는 animation을 구현해보려고 한다.
<Box transition={{ type: "spring", delay: 1 }} initial={{ scale: 0 }} // 애니메이션 초기 스티일 animate={{ scale: 1, rotateZ: 360 }} // 최종 스타일 />
원하는 요소에 초기 스타일인 initial과 최종 스타일인 animate을 주고
transition으로 원하는 효과를 주면 끝이다!https://www.framer.com/docs/transition/
다양한 효과가 있으니 위의 링크를 참고하여 무슨 효과를 줄지 정해보면 된다 : )
또한 구조적인 코드를 짜기위해 위의 코드를 variants로 관리 할 수 있다.
const myVars = { start: { scale: 0 }, end: { scale: 1, rotateZ: 360, transition: { type: "spring", delay: 1 } }, }; function App() { return ( <Wrapper> <Box variants={myVars} initial="start" animate="end" /> </Wrapper> ); }
variants={myVars}로 어디에 variants가 있는지 알려주고
initial="start"로 initial variants의 이름이 뭔지 알려주고
animate="end"로 finishing variants의 이름이 뭔지 알려주면 끝!
<Variants>
위의 영상이 처음에는 큰 정사각형이 나오고 크 후 각각 원들이 나오는 것 처럼
variants는 많은 애니메이션들을 하나로 연결시켜준다.
이처럼 부모 컴포넌트가 있고 부모 컴포넌트에 initial이름과 animate이름이 있고 variants가 있을 때
variants은 기본값으로 부모의 initial이름과 animate이름을 (start와 end를) 그 자식들에게 복붙해준다.
중요한 것은 자식에게 따로 효과를 주고싶을 때
부모에서 준 initial이름과 animate이름을 똑같이 해줘야한다는 것이다.
(부모의 initial과 animate을 상속하기 때문!)
예를들어
부모요소 Box가 있고 자식요소 Circle가 있을 때
부모요소 Box의 variants={boxVariants} initial="start" animate="end"를
자식요소 Circle에게 쓰지 않아도 Circle에게 상속이 된다!
그러니 Circle에게 따로 효과를 주고싶을 때
circleVariants에서 볼 수 있는 것 처럼 부모요소와 같은 initial이름과 animate이름을 적용해야한다.
+
delayChildren는 자식들을 기다리게 하는 효과이고
staggerChildren는 자식들에게 시간차로 딜레이를 주는 효과이다.
staggerChildren만 해주면 어떠한 복잡한 계산도 안해줘도 되기 때문에 매우 편리하다.
const boxVariants = { start: { opacity: 0, scale: 0.5, }, end: { scale: 1, opacity: 1, transition: { type: "spring", duration: 0.5, bounce: 0.5, delayChildren: 0.5, staggerChildren: 0.3, }, }, }; const circleVariants = { start: { opacity: 0, y: 10, }, end: { opacity: 1, y: 0, }, }; function App() { return ( <Wrapper> <Box variants={boxVariants} initial="start" animate="end"> <Circle variants={circleVariants} /> <Circle variants={circleVariants} /> <Circle variants={circleVariants} /> <Circle variants={circleVariants} /> </Box> </Wrapper> ); }
<Gestures / Drag>
Gestures
Gestures는 이벤트를 listen 하는 것이다.
예를들어 whileHover는 호버이벤트, whileTap는 클릭이벤트이다.
const circleVariants = { hover: { scale: 1.5, rotateZ: 90 }, click: { scale: 1, borderRadius: "100px" }, }; function App() { return ( <Wrapper> <Box variants={circleVariants} whileHover="hover" whileTap="click" /> </Wrapper> ); }
이렇게 쓸 수 있다 : )
Drag
Drag는 드래깅을 활성화한다.
<Box drag variants={circleVariants} whileHover="hover" whileTap="click" />
그런데 드래그이벤트를 주고
backgroundColor: "blue" 이런식으로 값을 주면 애니메이션을 할 수 없다.
backgroundColor: "rgba(46,204,113)" 이렇게 숫자값을 줘야 애니메이션이 된다.
- Gestures / Drag 코드정리
const circleVariants = { hover: { scale: 1.5, rotateZ: 90 }, click: { scale: 1, borderRadius: "100px" }, drag: { backgroundColor: "rgb(46, 204, 113)", transition: { duration: 10 } }, }; function App() { return ( <Wrapper> <Box drag variants={circleVariants} whileHover="hover" whileTap="click" whileDrag="drag" /> </Wrapper> ); }
Drag 제약
Drag에 제약을 줄 수 있다.
예를들어 스크롤을 잠가버릴 수 있는데
drag=”x” 는 x축으로만 이동 가능, drag=”y” 는 y축으로만 이동 가능하다.
그리고
dragConstraints={{ top: -50, bottom: 50, left: -50, right: 50 }} 는 드래깅이 허용될 수 있는 영역 Box를 만들 수 있다.
dragSnapToPrigin는 중앙으로 되돌아오게하는 힘이 생기게 해준다.
dragElastic는 0과 1 사이의 값이어야 하고 1이면 어디든지 갈 수 있다.(“당기는 힘” 같은 게 있다는 의미!)
const biggerBoxRef = useRef<HTMLDivElement>(null)는 useRef로 움직일 수 있는 영역을 잡아준다!
const boxVariants = { hover: { rotateZ: 90 }, click: { borderRadius: "100px" }, }; function App() { const biggerBoxRef = useRef<HTMLDivElement>(null); return ( <Wrapper> <BiggerBox ref={biggerBoxRef}> <Box drag dragSnapToOrigin dragElastic={0.5} dragConstraints={biggerBoxRef} variants={boxVariants} whileHover="hover" whileTap="click" /> </BiggerBox> </Wrapper> ); }
'프론트엔드 개발자가 될거야. > 라이브러리' 카테고리의 다른 글
[React-i18next] 웹페이지에 '더 효율적으로' 다국어 적용하기 (with: typescript) (0) 2023.03.09 [React-i18next] 웹페이지에 다국어 적용하기 (with: typescript) (0) 2023.03.02 [react-beautiful-dnd] 칸반보드 만들기, react-beautiful-dnd 상세설명 (0) 2023.01.07 리액트 캘린더 라이브러리 Datepicker 사용법, 커스텀하기 (0) 2022.08.07