npm i framer-motion
그 후 framer motion을 사용할 컴포넌트에서
import { motion } from "framer-motion"
으로 불러온다.
import { motion } from "framer-motion"
function App () {
return (
<main>
// motion으로부터 HTML element를 불러온다.
<motion.div></motion.div>
</main>
)
}
export default App;
: 요소의 모든 움직임 정의
Framer Motion Doc: Animation
- animate 속성을 통해 제어된다.
: 한 상태에서 다른 상태로 움직이는 방식 정의
Framer Motion Doc: Transition
- transition 속성을 통해 제어된다.
- props로는 type의
Tween
,Spring
,Inertia
가 있다.- 또한
stiffness
와damping
,bounce
,mass
등이 있다.
function App () {
return (
<main>
// motion으로 된 styled-component
<Box
// element의 초기상태 지정
initial={{ scale: 0 }}
animate={{ scale: 1, rotateZ: 360 }}
transition={{ type= "spring", damping: 10 }}
/>
</main>
)
}
const Box = styled(motion.div)`
width: 200px;
height: 200px;
`;
export default App;
: 애니메이션 객체를 생성하고, 자식 요소의 애니메이션도 제어할 때
Framer Motion Doc: Introduction/##variants
Variants는 애니메이션 객체를 생성하여 코드를 깔끔하게 만들어줄 뿐만 아니라 부모 요소에 Variants를 등록했을 때 안의 자식 요소들에게까지 그 Variants을 전달한다. 똑같이 등록할 필요가 읎음!variants 대표 기능
- 애니메이션 객체 생성
- Orchestration 로 자식 컴포넌트 애니메이션까지 제어 가능
delayChildren
staggerChildren
staggerDirection
when
// variants객체 생성
const boxVars = { // 부모의 variants 객체
start: {
opacity: 0,
scale: 0.5,
},
end: {
opacity: 1,
scale: 1,
rotateZ: 360,
transition: {
type= "spring",
duration: 0.5,
bounce: 0.5,
delayChildren: 0.5, // 자식 컴포넌트는 0.5초 느리게 나타나게 하는 속성
staggerChildren: 0.2, // 자식 컴포넌트 하나 나타나고 그다음 컴포넌트에 0.2초 딜레이 부여
}
}
}
const circleVars = { // 자식의 variants 객체
start: {
opacity: 0,
y: 10
},
end: {
opacity: 1,
y: 0,
},
}
function App () {
return (
<main>
<Box
variants={boxVars} // 부모 variants 등록
initial="start" // boxVars 객체에 있는 키값과 동일하게 작성해야함
animate="end"
>
// 부모 컴포넌트 Box 객체 키값을 상속받음!
// 자식은 부모의 initial="start" animate="end"를 상속받는다고 생각하면 된다.
// 그래서 자식 variants를 생성할 때 키값을 동일하게 작성해주는 것이 중요하다!
<circle variants={circleVars} >
<circle variants={circleVars} >
<circle variants={circleVars} >
<circle variants={circleVars} >
</Box>
</main>
)
}
framer motion 속성들을 하나의 객체로 만들어줌으로써 컴포넌트가 좀 더 깔끔해졌다.
: drag, hover, tap, pan, viewport를 감지해 애니메이션 지원. 마우스 상태에 따른 몇몇 이벤트 리스닝 제공. 사용자의 움직임과 상호작용하고 싶다면 Gestures 을 사용하면 된다.
Framer Motion Doc: Gestures
- Gesture animation props
whileHover
: 커서가 컴포넌트 위로 이동하거나 떠날 때 동안의 애니메이션 속성.whileTap
: 컴포넌트를 클릭하고 있는 동안의 애니메이션 속성whileFocus
: 컴포넌트를 클릭해 포커스된 동안의 애니메이션 속성whileDrag
: 끌기 제스쳐가 발생하는 동안의 애니메이션 속성whileInView
: 보통 스크롤 할 때 사용, 내리면서 컴포넌트가 뷰포트에 있는 동안의 애니메이션 속성
const boxVars = {
hover: { scale: 2 rotateZ: 90 },
click: { scale: 1 borderRadius: "50px" },
drag: { backgroundColor: "rgb(165, 102, 255) },
transition
}
function App () {
const ParentsBoxRef = useRef<HTMLDivElement>(null);
return (
<main>
<ParentsBox ref={ParentsBoxRef}>
<Box
variants={boxVars}
whileHover="hover" // 커서를 올려놓는 동안
whileTap="click" // 클릭하는 동안
drag // 끌기 등록
// drag="x" 는 x축으로만 움직일 수 있도록 제한.
// y는 y축으로만.
dragConstraints={ParentsBoxRef} // 끌기 영역 제한 설정
dragElasic={0.3} // 0 ~ 1 사이 값, 제한 영역 밖으로 나가도 보이긴 함.
dragSnapToOrigin // 아무리 멀리 끌어도 제자리로 돌아감, 제한 영역 밖으로 나가면 안 보임
whileDrag="drag" // 끄는 동안의 애니메이션
/>
</ParentsBox>
</main>
)
}
애니메이션 값의 상태와 속도를 추적한다. 그렇지만 React State가 아니기 때문에 모션값의 상태가 바뀌어도 리렌더링 되지 않는다. 위치에 따라 애니메이션을 다르게 설정할 수 있다.
Framer Motion Doc: MotionValue
useMotionValue()
:MotionValue를 얻어올 변수 정의, 모션 컴포넌트의 style 속성에 연결useTransform()
:MotionValue값에 따라 다른 애니메이션을 도출하고 싶을 때 사용하는 훅const x = useMotionValue(0) // x축 값 const input = [-200, 0, 200] // x축 범위 인풋 const output = [2, 1, 2] // scale 범위 아웃풋 const scale = useTransform(x, input, output)
useViewportScroll()
scrollX
: 실제 수평 스크롤 픽셀 ex) 500pxscrollY
: 실제 수직 스크롤 픽셀 ex) 500pxscrollXProgress
: 0 ~ 1 사이의 수평 스크롤scrollYProgress
: 0 ~ 1 사이의 수직 스크롤(가장 상단 0, 가장 하단 1)get()
set()
onChange()
import {motion, useMotionValue, useTransform} from "framer-motion";
export function MyComponent() {
const x = useMotionValue(0) // default = 0
const scale = useTransform(x, [-200, 0, 200], [2, 1, 2]);
const gradient = useTransform(
x,
[-200, 200],
[
"linear-gradient(135deg, rgb(0, 210, 238), rgb(0, 83, 238))",
"linear-gradient(135deg, rgb(0, 238, 155), rgb(238, 178, 0))",
]
)
return (
// useMotionValue()
<motion.div style={{ backgroundColor: gradient }}>
// x.set()로 값을 업데이트해 해당 컴포넌트의 위치를 조작할 수 있다. get()과 onChange()도 있음.
<button onClick={() => x.set(200)}>click me</button>
<motion.div style={{ x, scale }} drag="x" />
</motion.div>
)
}
import {motion, useTransform, useViewportScroll} from "framer-motion";
function App () {
const { scrollYProgress } = useViewportScroll();
const scale = useTransform(scrollYProgress, [0, 1], [1, 3]);
return (
<motion.div>
<motion.div style={{ scale }}>
</motion.div>
)
}
svg의 속성들을 이용하여 다양한 애니메이션을 만들어낼 수 있다.
SVG 속성
width
: 도형의 너비height
: 도형의 높이stroke
: 도형의 테두리 색상stroke-width
: 도형의 테두리 굵기fill
: 도형을 채울 색상opacity
: 도형의 투명도
const svg = {
start: {
fill: "rgba(255,255,255,0)",
pathLength: 0, // 선이 그려지는 정도 0 ~ 1
stroke: "white", // 선
strokeWidth: 2, // 선 굵기
d: "...(코드중략)",
},
end: {
fill: "rgba(255,255,255,1)",
pathLength: 1,
transition: {
// 특정 property만 더 나중으로 딜레이되도록 만들기
default: { duration: 5 }, // 모든 요소는 5초 동안
fill: { duration: 2, delay: 3 }, // fill요소는 5초 후 2초 동안
},
},
};
function App () {
return (
// 부모 요소인 svg는 motion element가 아니어도 되지만 그 안의 자식요소인 path는 motion element여야 한다.
<svg>
<motion.path
variants={svg}
initial="start"
animate="end"
>
</motion.path>
</svg>
)
}
기억할만한 것은 transition 부분에서 어떤 특정 속성만 애니메이션 값을 다르게 주고 싶을 때
transition: {
default: { 모든 요소에 적용 },
특정속성명: { 특정 요소에만 적용}
}
이렇게 적어주면 된다는 것이다.
AnimatePresence는 React App에서 사라지는 컴포넌트에 애니메이션 효과를 줄 수 있다. React 자체에서는 컴포넌트가 사라지면 그냥 끝이라서 라이프사이클로 어떤 효과도 줄 수 없지만 motion에서는 사라지는 컴포넌트에 애니메이션 효과를 줄 수 있다.
Framer Motion Doc: animate-presence
exit
: 이 property가 있는 컴포넌트가 바로 애니메이션 대상이다.
import {motion, AnimatePresence} from "framer-motion";
function App = ({ isVisible }) => (
// AnimatePresence로 감싸준다.
<AnimatePresence>
{isVisible && (
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }} // 이 속성으로 사라질 때의 애니메이션 효과를 줄 수 있다.
/>
)}
</AnimatePresence>
)
framer-motion은 Variants, Gesture, MotionValues 등 개념만 알고 나면 정말 쉽게 애니메이션 도움을 받을 수 있는 라이브러리다. 정말 다양한 효과를 줄 수 있어서 화려한 효과가 필요한 UI에 자주 애용할 것 같다.
특히 컴포넌트가 사라질 때 줄 수 있는 애니메이션 효과라니!👍 또 자식 컴포넌트들이 부모의 애니메이션을 상속받는 것이나 자식들이 순서대로 효과를 나타내는 staggerChildren 등 유용한 기능이 짱 많당.
지금 이 포스트에서 framer-motion들의 개념을 포함의 일부 기능만 작성했다. 모든 걸 작성하기에는 스크롤의 압박이 심해져서 다음 포스트에 작성해보려고 한다
👏👏
그럼 20000!