본문 바로가기

FrontEnd

프레이머 모션[Framer Motion] 기초 1편 : 생기초 알아보기

반응형

원문 보기

https://blog.maximeheckel.com/posts/guide-animations-spark-joy-framer-motion/

 

Guide to creating animations that spark joy with Framer Motion - Maxime Heckel's Blog

An interactive guide introducing everything I've learned about Framer Motion through fun examples and little case studies of animations I built.

blog.maximeheckel.com

아래에서 다루는 예제들

원문은 영어로 읽는데 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부작이더라.

다음에 좀 더 심화된 예제들을 다뤄보자

반응형