Front/React

Framer Motion - 리액트 라이브러리, 애니메이션 구현

oodada 2023. 11. 4. 22:18

Framer Motion - 리액트 라이브러리

Framer Motion은 단순하면서도 강력한 React용 모션 라이브러리이다.

1. 설치하기

yarn add framer-motion
npm install framer-motion

2. 기본 사용법

  • import { motion } from 'framer-motion'; 으로 motion을 불러옵니다.
  • motion이 들어갈 요소에 motion을 붙여줍니다.
  • initial(초기값)과 animate(애니메이션)을 설정합니다.
  • styled-components를 사용하는 경우에는 styled(motion.div)로 사용합니다.
import { motion } from 'framer-motion';
import styled from 'styled-components';

export default function App() {
    const box = {
        width: '200px',
        height: '200px',
        borderRadius: '50%',
        background: 'blue',
    };
    return (
        <>
            <motion.div style={box} initial={{ opacity: 0 }} animate={{ opacity: 1, x: 100 }} />
            <MotionOpacity initial={{ opacity: 0 }} animate={{ opacity: 1, scale: 1.2, y: -100 }} />
        </>
    );
}

const MotionOpacity = styled(motion.div)`
    width: 200px;
    height: 200px;
    background: red;
`;

3. 옵션 정리

속성 설명
initial 초기 값 설정
animate 애니메이션 설정
Transition 애니메이션 시간, 이징 등 설정
Variants 애니메이션 유형 설정
whileHover 마우스 호버 시 애니메이션 설정
whileTap 마우스 클릭 시 애니메이션 설정
whileFocus 포커스 시 애니메이션 설정
whileDrag 드래깅 시 애니메이션 설정
exit 요소 사라질 때 애니메이션 설정
animatePresence 요소 사라질 때 애니메이션 설정
drag 드래그 설정
dragConstraints 드래그 범위 설정
dragElastic 드래그 탄성 설정
dragMomentum 드래그 관성 설정
dragPropagation 드래그 전파 설정
layout 레이아웃 설정
layoutId 레이아웃 ID 설정
layoutTransition 레이아웃 애니메이션 설정
onHoverStart 마우스 호버 시작 이벤트 설정
onHoverEnd 마우스 호버 종료 이벤트 설정
onTap 마우스 클릭 이벤트 설정
onFocus 포커스 이벤트 설정
onDragStart 드래깅 시작 이벤트 설정
onDragEnd 드래깅 종료 이벤트 설정
onDrag 드래깅 이벤트 설정
onDragTransitionEnd 드래그 애니메이션 종료 이벤트 설정
onLayoutAnimationComplete 레이아웃 애니메이션 완료 이벤트 설정
onPanStart 팬 시작 이벤트 설정
onPanEnd 팬 종료 이벤트 설정
onPan 팬 이벤트 설정
onPanTransitionEnd 팬 애니메이션 종료 이벤트 설정

4. 애니메이션

Simple animations, transitions

  • x, y, scale, rotate, opacity, backgroundColor, borderRadius 등의 애니메이션을 사용할 수 있습니다.

https://codesandbox.io/s/framer-motion-enter-animation-forked-3sdxyz?file=/src/App.tsx

<motion.div
    initial={{ opacity: 0, x: -100, scale: 0.5 }}
    animate={{ opacity: 1, x: 0, scale: 2 }}
    transition={{ ease: 'easeOut', duration: 2 }}
/>

Keyframes

  • keyframes를 사용하면 애니메이션을 더 세밀하게 조정할 수 있습니다.

https://codesandbox.io/s/framer-motion-keyframes-0fzv21?from-embed

<motion.div
    className="box"
    animate={{
        scale: [1, 2, 2, 1, 1],
        rotate: [0, 0, 270, 270, 0],
        borderRadius: ['20%', '20%', '50%', '50%', '20%'],
    }}
    transition={{
        duration: 2,
        ease: 'easeInOut',
        times: [0, 0.2, 0.5, 0.8, 1],
        repeat: Infinity,
        repeatDelay: 1,
    }}
/>
  • keyframes의 초기값에 null을 전달하여 현재 값을 초기 키프레임으로 사용할 수 있습니다.

https://codesandbox.io/s/framer-motion-wildcard-keyframes-dkk0xr?from-embed=&file=/src/App.tsx

<motion.div animate={{ x: [null, 100, 0] }} />

Variants

  • variants를 사용하여 애니메이션을 변수로 관리할 수 있습니다.

https://codesandbox.io/s/framer-motion-side-menu-mx2rw?from-embed

import { motion } from 'framer-motion';

const variants = {
    // 애니메이션 변수
    open: { opacity: 1, x: 0 }, // open 상태
    closed: { opacity: 0, x: '-100%' }, // closed 상태
};

export const MyComponent = () => {
    const [isOpen, setIsOpen] = useState(false); // isOpen 상태 관리

    return (
        // isOpen 상태에 따라 애니메이션 적용
        // isOpen 상태 변경
        <motion.nav animate={isOpen ? 'open' : 'closed'} variants={variants}>
            <Toggle onClick={() => setIsOpen((isOpen) => !isOpen)} />
            <Items />
        </motion.nav>
    );
};

gestures

Hover

  • 마우스 호버 시 애니메이션을 설정할 수 있습니다.
<motion.div whileHover={{ scale: 1.2 }} />

Tap

  • 마우스 클릭 시 애니메이션을 설정할 수 있습니다.
<motion.div whileTap={{ scale: 0.8 }} />

Focus

  • 포커스 시 애니메이션을 설정할 수 있습니다.
<motion.div whileFocus={{ scale: 1.2 }} />

drag

  • 드래그 시 애니메이션을 설정할 수 있습니다.
<motion.div whileDrag={{ scale: 0.8 }} />

주요 예제

1. State, Variants

https://codesandbox.io/s/framer-motion-variants-rj7ks0?from-embed=&file=/src/App.tsx:0-1980

import './styles.css';
import { useState } from 'react';
import { motion, Variants } from 'framer-motion';

const itemVariants: Variants = {
    open: {
        opacity: 1,
        y: 0,
        transition: { type: 'spring', stiffness: 300, damping: 24 },
    },
    closed: { opacity: 0, y: 20, transition: { duration: 0.2 } },
};

export default function App() {
    const [isOpen, setIsOpen] = useState(false);

    return (
        <motion.nav initial={false} animate={isOpen ? 'open' : 'closed'} className="menu">
            <motion.button whileTap={{ scale: 0.97 }} onClick={() => setIsOpen(!isOpen)}>
                Menu
                <motion.div
                    variants={{
                        open: { rotate: 180 },
                        closed: { rotate: 0 },
                    }}
                    transition={{ duration: 0.2 }}
                    style={{ originY: 0.55 }}
                >
                    <svg width="15" height="15" viewBox="0 0 20 20">
                        <path d="M0 7 L 20 7 L 10 16" />
                    </svg>
                </motion.div>
            </motion.button>
            <motion.ul
                variants={{
                    open: {
                        clipPath: 'inset(0% 0% 0% 0% round 10px)',
                        transition: {
                            type: 'spring',
                            bounce: 0,
                            duration: 0.7,
                            delayChildren: 0.3,
                            staggerChildren: 0.05,
                        },
                    },
                    closed: {
                        clipPath: 'inset(10% 50% 90% 50% round 10px)',
                        transition: {
                            type: 'spring',
                            bounce: 0,
                            duration: 0.3,
                        },
                    },
                }}
                style={{ pointerEvents: isOpen ? 'auto' : 'none' }}
            >
                <motion.li variants={itemVariants}>Item 1 </motion.li>
                <motion.li variants={itemVariants}>Item 2 </motion.li>
                <motion.li variants={itemVariants}>Item 3 </motion.li>
                <motion.li variants={itemVariants}>Item 4 </motion.li>
                <motion.li variants={itemVariants}>Item 5 </motion.li>
            </motion.ul>
        </motion.nav>
    );
}

'Front > React' 카테고리의 다른 글

React GitHub 배포, Netlify 배포  (0) 2023.11.13
React Library  (0) 2023.11.06
상태(State) - React 배우기  (0) 2023.10.31
이벤트(Event) - React 배우기  (0) 2023.10.31
속성(Props, Properties) - React 배우기  (0) 2023.10.29
티스토리 친구하기