본문 바로가기
JavaScript/React

[React] Framer-motion 애니메이션 라이브러리

by dev또리 2023. 4. 21.
728x90

 

Framer-motion은 Framer가 제공하는 리액트용 애니메이션 라이브러리다. 

 

 

설치

$ npm i framer-motion

 

 

사용법

import { motion } from "framer-motion"

 

 

motion.div 와 같이, HTML 태그 앞에 motion 키워드를 붙여준다.

motion 키워드가 붙은 요소를 motion component 라고 한다.

초기 상태를 initial 속성에 객체 형태로 넣고, 애니메이션 할 상태를 animate 속성에 객체 형태로 넣는다.

 


Transitions

import "./styles.css";
import { motion } from "framer-motion";

export default function App() {
  return (
    <motion.div
      className="box"
      initial={{ opacity: 0, scale: 0.5 }}
      animate={{ opacity: 1, scale: 1 }}
      transition={{
        duration: 0.8,
        delay: 0.5,
        ease: [0, 0.71, 0.2, 1.01]
      }}
    />
  );
}

 

 

 

Orchestration

import { motion } from "framer-motion";
import "./styles.css";

export default function App() {
  const list = {
    hidden: {
      opacity: 0
    },
    visible: {
      opacity: 1,
      transition: {
        when: "beforeChildren",
        staggerChildren: 0.2
      }
    }
  };

  const item = {
    hidden: { opacity: 0, y: 50 },
    visible: { opacity: 1, y: 0 }
  };

  return (
    <div className="wrap">
      <motion.ul variants={list} initial="hidden" animate="visible">
        <motion.li variants={item}>item 1</motion.li>
        <motion.li variants={item}>item 2</motion.li>
        <motion.li variants={item}>item 3</motion.li>
      </motion.ul>
    </div>
  );
}

 

 

 

Hover 

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

onMouseEnter나 onMouseLeave 와는 다르게 실제 마우스 이벤트 결과가 있을 때만 실행된다.

 

import "./styles.css";
import { motion } from "framer-motion";

export default function App() {
  return (
    <motion.div
      className="box"
      whileHover={{ scale: 1.1 }}
      transition={{ type: "spring", stiffness: 400, damping: 10 }}
    />
  );
}

 

 

 

 

Spring

 

Motion의 좋은 점은 보다 사실적인 애니메이션을 표현해 준다는 것이다.
transition 타입으로 spring을 설정하면 용수철이 튀어오르는 것처럼 사실적인 물리 표현을 할 수 있다.

  • bounce (number)
    말그대로 얼마나 바운스바운스할지 정합니다(두근..!) 0이라면 탄력이 없고, 1은 매우 탄력적이다. duration 기본값은 0.25로 설정된다.
  • damping (number)
    저항하는 반대 힘. 0으로 설정하면 스프링이 무한으로 빠운스한다. (기본값: 10)
  • mass (number)
    질량. 값이 높을수록 움직임이 둔해진다. (기본값: 1)
  • stiffness (number)
    값이 높을수록 더 갑작스럽게 움직인다. (기본값: 100)
  • velocity (number)
    스프링의 초기 속도.
  • restSpeed (number)
    절대 속도가 이 값 아래로 떨어지고 델타가 restDelta보다 작으면 애니메이션을 종료한다. (기본값: 0.01)
  • restDelta (number)
    거리(distance)가 이 값보다 작고 속도가 restSpeed 보다 작으면 애니메이션을 종료한다. (기본값: 0.01)
import { useEffect, useState } from "react";
import { motion, useAnimationControls } from "framer-motion";
import "./styles.css";

export default function App() {
  return (
    <div className="wrap">
      <article>
        <strong>No Transition</strong>
        <motion.div className="box" whileHover={{ scale: 1.3 }} />
      </article>

      <article>
        <strong>Type: "spring"</strong>
        <motion.div
          className="box"
          whileHover={{ scale: 1.3 }}
          transition={{ type: "spring" }}
        />
      </article>

      <article>
        <strong>Damping: 1</strong>
        <motion.div
          className="box"
          whileHover={{ scale: 1.3 }}
          transition={{ type: "spring", damping: 1 }}
        />
      </article>

      <article>
        <strong>Mass: 2</strong>
        <motion.div
          className="box"
          whileHover={{ scale: 1.3 }}
          transition={{ type: "spring", damping: 1, mass: 2 }}
        />
      </article>

      <article>
        <strong>Stiffness: 300</strong>
        <motion.div
          className="box"
          whileHover={{ scale: 1.3 }}
          transition={{ type: "spring", damping: 1, mass: 2, stiffness: 300 }}
        />
      </article>

      <article>
        <strong>Velocity: 10</strong>
        <motion.div
          className="box"
          whileHover={{ scale: 1.3 }}
          transition={{
            type: "spring",
            damping: 1,
            mass: 2,
            stiffness: 300,
            velocity: 10
          }}
        />
      </article>
    </div>
  );
}
728x90

댓글