[React] Framer Motion

bomhada·2022년 4월 20일
0

📘 React study 

목록 보기
10/15
post-thumbnail

Framer Motion

React에서 사용할 수 있는 production-ready 모션 라이브러리 입니다.
공식 홈페이지
공식 GitHub

설치

npm i framer-motion

react 버전4를 사용하는 분들은 CRACO를 이용해 에러를 해결하세요.
CRACO(Create React App Configuration Override)는 create-react-app을 위한 configuration레이어 입니다.

사용법

animation을 사용하기 위해서는 일반 HTML 테그를 사용할 수 없고, 꺽쇠안에 motion을 아래와 같이 넣어줘야합니다.

<moiton.div></motion.div>

혹은 styled-components와 같이 사용을 하기 위해서는 아래와 같이 작성해줘야 합니다.

import {motion} from "framer-motion";
import styled from "styled-components";

const Box = styled(motion.div)``;

funtion App() {
  return(
  	<Box />
  );
}

export default App;

Animation

Framer Motion의 애니메이션은 모션 컴포넌트의 유연한 animate 속성을 통해 제어됩니다.
간단한 애니메이션의 경우 animate props에서 직접 설정할 수 있습니다.

<Box animate={{ rotate: 360 }} transition={{ duration: 2 }}/>

Transition

Transition은 값이 한 상태에서 다른 상태로 움직이는 방식을 정의합니다.
type을 통해서 Tween, spring과 같은 애니메이션의 유형을 설정할 수 있습니다.
기본 type 값은 spring 입니다.

<Box animate={{ rotate: 360 }} transition={{ type: "Tween" }}/>

Variants

Variants는 컴포넌트가 가질 수 있는 미리 정의 된 시각적 state입니다.

const BoxVariants = {
  start: { opacity: 0.1 },
  end: { opacity: 1,
    transition: {
      duration: 1.5,
      delay: 1,
    },
  },
}

<Box variants={BoxVariants} initial="start" animate="end"/>

Orchestration

delayChildren: 딜레이 시간(초) 후에 하위 애니메이션이 시작됩니다.
staggerChildren: 하위 컴포넌트의 애니메이션에 지속 시간만큼 시차를 둘 수 있습니다.

const BiggerVariants = {
  start: { opacity: 0.1 },
  end: { opacity: 1,
    transition: {
      delay: 1,
      duration: 1.5,
      delayChildren: 1.5,
      staggerChildren:0.1
    },
  },
}

const BoxVariants = {
   start: {
     opacity: 0,
     y: -10,
  },
  end: {
    opacity: 1,
    y: 0,
  }
}

<BiggerBox variants={BiggerVariants} initial="start" animate="end">
  <Box variants={BoxVariants}/>
  <Box variants={BoxVariants}/>
  <Box variants={BoxVariants}/>
  <Box variants={BoxVariants}/>
</BiggerBox>

🚨 부모 컴포넌트의 state값은 자식에게도 그대로 전달이 되는데, 자식에게도 새로운 state를 설정해 다른 애니메이션을 줄 수도 있습니다.

Hover

Hover 제스처는 포인터가 컴포넌트 위로 이동하거나 컴포넌트를 떠날 때를 감지합니다.

const BoxVariants = {
  hover: { scale: 0.5 },
}

<Box variants={BoxVariants} whileHover="hover" />

Tap

컴포넌트를 클릭하고 있는 동안 애니메이션할 속성 또는 변형 레이블입니다.

const BoxVariants = {
  click: { scale: 0.5 },
}

<Box variants={BoxVariants} whileTap="click" />

Drag

제약 없이 드래그를 하려면 컴포넌트에 Drag만 넣어주면 됩니다.
만약 특정 방향으로만 드래그하려면 "x" 또는 "y"로 설정합니다.

const BoxVariants = {
  drag: {
    // backgroundColor: "tomato",
    backgroundColor: "rgb(255, 106, 86)",
    transition: {
      duration: 1.5,
    }
  },
}

<Box drag="x" variants={BoxVariants} whileDrag="drag" />

🚨 만약 backgroundColor 값에 blue나 tomato같은 값을 넣는다면 string이기 때문에 애니메이션이 나타나지 않습니다.
하지만 코드 = rgb값을 넣는다면 애니메이션이 실행됩니다. 그리고 transition값도 설정 할 수 있습니다.

dragSnapToOrigin

true인 경우 드래그 가능한 요소는 드래그를 놓을 때, 원점으로 다시 애니메이션됩니다.

<Box drag dragSnapToOrigin />

dragElastic

아이템을 드래그 시 원점에서 움직임을 허용하는 정도입니다.
0 = 움직임 없음, 1 = 전체 움직임, 기본 값은 0.5입니다.

<Box drag dragElastic={0.2} />

dragConstraints

드래그가 가능하도록 허용될 수 있는 영역을 설정할 수 있습니다.
dragConstraints에는 드래그 가능한 컴포넌트의 가장자리 거리를 정의합니다.
(드래그 가능한 영역에 가장자리에서 얼마만큼까지 허용할 것인지 지정)
props로 직접 설정도 가능합니다.

직접 설정


< BiggerBox>
  < Box drag dragConstraints={{
    top: 0, bottom: 50, left: 0, right: 50
  }} />
< /BiggerBox>

useRef 사용

const BoxRef = useRef(null);

< BiggerBox ref={BoxRef}>
  < Box drag dragConstraints={BoxRef} />
< /BiggerBox>

Motion Value

MotionValues를 애니메이션 값의 상태와 속도를 추적합니다.
모든 모션 컴포넌트는 내부적으로 MotionValues를 사용하여 애니메이션 값의 상태와 속도를 추적합니다.
🚨 MotionValues는 react의 state값이 아니기 때문에 MotionValues의 값이 변하더라도 리랜더링이 되지 않습니다.
하지만 get 메소드로 확인할 수 있습니다.

onst x = useMotionValue(0);

useEffect(() => {
  x.onChange(() => console.log(x.get()));
}, [x]);

<Box
  style={{ x }}
  drag="x"
  dragSnapToOrigin
/>

x.set(100)

set 메소드로 x의 값을 업데이트할 수 있습니다.
이 때, react에서 리랜더링을 트리거 하지 않습니다.

x.get(100)

get 메소드로는 값을 읽을 수 있습니다.
MotionValue는 뭄자열이나 숫자가 될 수 있습니다.

useTransform

useTransform 훅을 통해 MotionValues를 연결합니다.
useTRansform() 안에는 세가지 요소가 들어가는데, 첫 번째 요소로는 아이템이 변경 할 때마다 새로 설정되는 값을 넣어야합니다. 위에 설명한 것과 같이 MotionValue를 통해 값을 가져오면 됩니다.
두 번째로는 원하는 값을 배열에 넣습니다. 세 번째 인자로는 output을 넣습니다.

const scale = useTransform(x, [-400, 0, 400], [2, 1, 2]);

위 코드는 x축의 값이 -400일때 scale 값이 2, 중간이면 scale 값이 1, 400일때 scale 값이 2라는 뜻입니다.
위 상수를 컴포넌트의 style에 넣으면 됩니다.

useViewportScroll()

뷰포트가 스크롤될 때 업데이트되는 MotionValues를 리턴합니다.
아래 값들은 모두 MotionValue< number >를 넘겨줍니다.
scrollX: 실제 수평 스크롤 픽셀 ex) 500px
scrollY: 실제 수직 스크롤 픽셀 ex) 500px
scrollXProgress : 0 ~ 1 사이의 수평 스크롤
scrollYProgress : 0 ~ 1 사이의 수직 스크롤(가장 상단 0, 가장 하단 1)

const { scrollYProgress } = useViewportScroll();
const scale = useTransform(scrollYProgress, [0, 1], [0.2, 1]);

<motion.div style={{ x }} />

AnimatePresence

AnimatePresence를 사용하면 React 트리에서 컴포넌트가 제거될 때 제거되는 컴포넌트에 애니메이션 효과를 줄 수 있습니다. 이 때, React에는 다음과 같은 생명주기 메서드가 없기 때문에 exit props를 사용해 활성화하고, 애니메이션 효과를 줄 수 있습니다.

const BoxVars = {
  initial: {
    scale: 0,
    opacity: 0,
  },
  visible: {
    scale: 1,
    opacity: 1,
    rotate: 180,
  },
  invisible: {
    opacity: 0,
    y: -20,
  },
}

const [isShowing, setShowing] = useState(false);
const onClick = () => setShowing(prev => !prev);
  
<Wrapper>
  <AnimatePresence>
    {isShowing ?
      <Box
        variants={BoxVars}
        initial="initial"
        animate="visible"
        exit="invisible"
      />
      : null
    }
  </AnimatePresence>
  <Button onClick={onClick}>click</Button>
</Wrapper>

custom

각 애니메이션 컴포넌트에 대해 동적 variants를 다르게 적용할 때 사용할 수 있는 사용자 지정 데이터 입니다.
공식 문서 확인하기

exitBeforeEnter

true로 설정하면 AnimatePresence는 한 번에 하나의 컴포넌트만 랜더링합니다.
exiting 중인 컴포넌트가 완료될 때까지 기다렸다가 다음 컴포넌트가 애니메이션을 시작합니다.
공식 문서 확인하기

Layout animation

layout

true인 경우 이 컴포넌트는 레이아웃이 변경될 댇 새 위치에 자동으로 애니메이션을 적용합니다.
크기나 위치가 변결 될 때 모션 컴포넌트의 레이아웃에 자동으로 애니메이션을 적용하려면 layout porp을 설정해줍니다.

function Layout() {
  const [toggle, setToggle] = useState(false);
  const clicked = () => setToggle(prev => !prev);
  return (
    <Wrapper onClick={clicked}>
      <Box>
        {toggle ? <Circle layoutId="move" /> : null}
      </Box>
      <Box>
        {toggle ? null : <Circle layoutId="move" />}
      </Box>
    </Wrapper>
  );
}

Syncing layout animations

모션 컴포넌트의 layout prop은 레이아웃이 변할 때마다, 자동으로 애니메이션을 적용합니다.

layoutId

동일한 layoutId prop을 가진 모션 컴포넌트들 간에 애니메이션을 적용할 수 있습니다.
layoutId가 있는 새 컴포넌트가 추가되고 다른 컴포넌가 제거되면 이전 컴포넌트에서 새 컴포넌트로 레이아웃 애니메이션을 수행합니다.

Framer Motion 코드

0개의 댓글