반응형
원문 보기
https://blog.maximeheckel.com/posts/guide-animations-spark-joy-framer-motion/
아래에서 다루는 예제들
원문은 영어로 읽는데 20분 정도 걸리는 상당한 분량입니다.
내용을 거의 3분 분량으로 쳐냈습니다.
대신 아래 코드를 유심히 살펴보면 됩니다.
프레이머 모션 애니메이션의 해부학
- 초기 상태
- 목표 상태
- 전환 방법
프레이머 모션에서는
- initial
- animate
- transition
으로 표현합니다
const Example1 = (
<motion.div
initial={{
x: 0,
rotate: 45
}}
animate={{
x: 1000,
rotate: 270
}}
transition={{
type: "spring",
duration: 100
}}
style={{ background: "pink", width: "20px", height: "20px" }}
/>
);
- animate prop을 whileHover 또는 whileTap과 같은 보다 구체적인 제스처 prop으로 대체할 수 있습니다.
- 애니메이션과 동일한 형태의 prop을 파라미터로 받습니다.
- Framer Motion 컴포넌트 애니메이션을 정의하려면 애니메이션 또는 제스처 프롭 하나가 필수입니다
- 라이브러리는 initial 및 transition이 정의되지 않은 경우 스마트 기본값을 제공합니다.
- 애니메이트 prop에서 설정한 속성에 따라 전환 유형(spring, tween, ease)도 달라집니다.
variants - 파라미터 다형성
variants은 애니메이션 prop에 해당하는 미리 정의된 애니메이션 객체 세트입니다.
import { motion } from 'framer-motion';
const AnimatedButton = () => {
const buttonVariants = {
hover: {
scale: 1.5,
},
pressed: {
scale: 0.5,
},
rest: {
scale: 1,
},
};
return (
<motion.button
initial="rest"
whileHover="hover"
whileTap="pressed"
variants={buttonVariants}
>
Click me!
</motion.button>
);
};
custom prop을 사용해 동적 variants를 구현 가능.
해당 함수는 하나의 인자와 하나의 애니메이션 프롭 타입의 리턴 값을 갖습니다.
const buttonVariants = {
hover: (isClicked: boolean) => ({
scale: isClicked ? 2 : 3,
rotate: isClicked ? 0 : 360
}),
pressed: {
scale: 0.95
},
clicked: {
scale: 2
},
notClicked: {
scale: 1
}
};
컴포넌트에는 아래와 같이 프롭 전달
variants={buttonVariants}
animate={isClicked ? "clicked" : "notClicked"}
whileHover="hover"
whileTap="pressed"
custom={isClicked}
transition={{
duration
}}
심화 애니메이션
- 우리는 애니메이션을 정의하는 주요 요소를 알고 있습니다 ✅
- 우리는 선언적으로 애니메이션을 정의하기 위해 variants을 사용하는 방법을 알고 있습니다 ✅
Motion Values
MotionValue는 하나의 애니메이션을 다른 애니메이션에 종속시키려는 경우에 유용합니다.
예를 들어 컴포넌트가 배율(scale)의 절반에 도달하면 불투명도(opacity)가 100%가 되도록 컴포넌트의 배율과 불투명도를 함께 묶을 수 있습니다.
- 응용 : 아이콘의 불투명도와 체크 표시의 길이가 비례하도록 > 길이가 0.5정도일 때 불투명도 1이 되도록
- 모션 밸류와 트랜스폼을 같이 사용
const pathLength = useMotionValue(0);
const opacity = useTransform(pathLength, [0, 0.5], [0, 1]);
const clipboardIconVariants = {
clicked: { opacity: 0 },
unclicked: { opacity: 1 }
};
const checkmarkIconVariants = {
clicked: { pathLength: 1 },
unclicked: { pathLength: 0 }
};
컴포넌트에는 아래와 같이 프롭 전달
animate={isClicked ? "clicked" : "unclicked"}
variants={clipboardIconVariants}
오케스트레이션
두가지의 타입이 있습니다.
- 지연 및 반복: "A 지점으로 이동한 다음 2초 후에 B 지점으로 이동합니다. 이를 반복합니다."
- 부모-자식: "부모가 먼저 나타난 다음 1초 뒤 자식이 차례로 나타납니다."
Delays and repetition
- 반복 타입을 미러에서 루프로 변경하고 반복 타입의 미묘한 변화를 관찰할 수 있습니다.
- 애니메이션을 3번이 아닌 무한 반복하도록 합니다.
- 초기 지연을 2초로 만들고 모든 반복 지연을 1초로 만들면 각 반복 사이에 애니메이션이 일시 중지되는 것을 관찰합니다.
transition={{
ease: 'easeInOut',
duration: 0.7,
delay: 1,
// 처음 동작 시작까지 딜레이
repeat: 3,
// repeat: Infinity,
repeatType: 'mirror', // 다시 돌아오는 것도 반복 횟수로 침
// repeatType : loop // 맨처음으로 텔레포트해서 반봅
repeatDelay: 0, // 반복 사이의 딜레이
// repeatDelay: 1,
}}
Parent-Children
애니메이션된 상위 컴포넌트와 관련하여 일부 하위 컴포넌트의 애니메이션을 지연하려는 경우 매우 유용합니다.
Framer Motion은 transition 객체가 다음과 같은 작업을 수행할 수 있도록 delayChildren 옵션을 제공합니다. transition: {
duration: 0.6,
// Both children will appear 1.2s AFTER the parent has appeared
delayChildren: 1.2,
},
childeren을 그룹으로 동시에 0.6초 씩 지연시킬 뿐만 아니라
이전 형제가 나타난 후 1초 후 나타도록 형제를 기준으로 각 child를 지연시키고 싶다면 어떻게 해야 할까요?
staggerChildren으로 쉽게 할 수 있습니다.
const boxVariants = {
out: {
y: 600
},
in: {
y: 0,
transition: {
duration: 2,
// The first child will appear AFTER the parrent has appeared on the screen
delayChildren: 4,
// The next sibling will appear 0.5s after the previous one
staggerChildren: 0.5
}
}
};
아래와 같은 재미있는 효과도 만들 수 있다.
const boxVariants = {
out: {
y: 600
},
in: {
y: 0,
transition: {
duration: 2,
// The first child will appear AFTER the parrent has appeared on the screen
delayChildren: 4,
// The next sibling will appear 0.5s after the previous one
staggerChildren: 0.5
}
}
};
const iconVariants = {
out: {
x: -200,
opacity: "0"
},
in: {
x: 0,
opacity: "100%"
}
};
해당 게시물은 3부작이더라.
다음에 좀 더 심화된 예제들을 다뤄보자
반응형
'FrontEnd' 카테고리의 다른 글
리액트 쿼리 : FAQ(자주 묻는 질문) (2) | 2022.07.17 |
---|---|
프레이머 모션[framer motion] 기초 2부 : 레이아웃 애니메이션 (0) | 2022.07.16 |
[css] fixed를 중첩할 경우 조심해야 할 점 (0) | 2022.07.14 |
리액트 성능 최적화 : children props를 이용하여 리렌더링 방지 (0) | 2022.07.09 |
개인적으로 생각해본 컴포넌트 설계론 + 카카오 FE 기술블로그 염탐 (0) | 2022.07.08 |