1.15~16- React masterClass (Framer motion1)

hun2__2·2022년 1월 16일
0

Have a fruitful vacation

목록 보기
18/24

Farmer motion을 사용해서 여러가지 애니메이션 동작을 공부해볼 것이다.

사용법은 먼전 npm i framer-motion으로 설치해주고
import를 해준 후import { motion } from "framer-motion";
모든 HTML tag들을 <div> => <motion.div> 이런식으로 바꿔줘야만 해당 tag에 farmer motion을 사용할 수 있다.

만약 CRA version4를 사용하고 있다면 현재 motion version5에서 EcmaScript module로 변경되었기 때문에 CRA에서 사용할 수 없다. 따라서 CRACO를 사용해서
craco.config.js에서 CRA의 설정사항을 커스텀해준다.
먼저 설치해주고 npm install @craco/craco --save
craco.config.js


@@ -0,0 +1,15 @@
module.exports = {
  webpack: {
    configure: {
      module: {
        rules: [
          {
            type: "javascript/auto",
            test: /\.mjs$/,
            include: /node_modules/,
          },
        ],
      },
    },
  },
};

로 커스텀해주면 정상적으로 작동할 수 있다.

cf)
EcmaScript module : 재사용을 위해 JS코드를 패키징 하는 공식 표준 형식이다.(ECMA에서 정함)
(참고 : https://nodejs.org/api/esm.html)
CRACO : create-react-app의 설정사항의 override해서 커스텀 할 수 있게 해준다.
(참고 : https://github.com/gsoft-inc/craco/blob/master/packages/craco/README.md#installation)

하지만 나는 CRA v5니깐 건너뛰고~

styled-component와 framer motion을 같이 사용하는 방법부터 배워보자!
아주 간단하게 const box = styled.div => const Box = styled(motion.div) 로 바꿔주면 된다! (react-router component를 사용하는 것과 동일한 방법!)

그럼이제 tag에 animation 기능을 아주 간단하게 사용할 수 있다!

      <Box
        initial={{ scale: 0 }}
        animate={{ scale: 1, rotateZ: 360, borderRadius: "20px" }}
        transition={{ type: "spring", delay: 0.5 }}
      />

이와같이 initial로 처음 시작부분의 모양을 결정해주고, aniamte으로 최종적인 부분을 결정해주고, transition으로 중간에 어떻게 바뀔 것인지 결정해주면 끝@@
매우 쉽게 애니메이션이 끝난다 ㅜㅠㅜㅜㅜ

저번학기때 aniamtion 안먹혀서 일주일동안 뺑이 친거 생각하면,,,,, 너무 감사한 라이브러리다ㅠㅠ

여기서 한 단계 더 나아가면 variants라는 기능이 있다. inline으로 적은 prop들을 더 깔끔하게 빼서 적는 방법이다.

const boxVars = {
  start: { scale: 0 },
  end: {
    scale: 1,
    rotateZ: 360,
    borderRadius: "20px",
    transition: { type: "spring", delay: 0.5 },
  },
};

해당 하는 obj를 만들어주고 variants에 obj를 할당해주고 initial, animate에 각각 key값을 적어주면 된다!1

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

variants은 내 애니메이션에 사용하는 stage라고 생각하면 된다.

이제 Framer motion의 예시 애니메이션을 만들면서 익혀보자!
여기의 기능들을 만들 것이다.

먼저 데모를 만들기 위해사용하며 알아야 할 것들이다.

  1. initial은 시작 상태를 나타낸다.
  2. animate는 끝나는 상태를 나타낸다.
  3. transition은 중간에 과정을 나타낸다.
  4. drag기능
    dragConstaraints로 제약 공간을 만들 수 있다.
    dragSnapToOrigin 설정으로 drop공간을 원래 자리로 변경가능
    dragElastic 설정으로 관성력을 만들 수 있다.
  5. useMotionValue로 모션에따른 값 가져와서 사용하기
    useTransform(value, [value input 값 array], [value output 값 array]) 설정으로 내가 원하는 animation 설정가능
  6. 각 설정값 transition 다르게 주기

위와같은 값들로 demo를 만들어보면
box1

const boxVariants = {
  start: {
    scale: 0,
  },
  end: {
    scale: 1,
    rotateZ: 360,
    transition: {
      type: "spring",
      duration: 2,
      bounce: 0.5,
    },
  },
};

// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
  return <Box variants={boxVariants} initial="start" animate="end"></Box>;
}

box2

const boxVariants = {
  start: {
    scale: 0,
    opacity: 0,
  },
  end: {
    scale: 1,
    opacity: 1,
    transition: {
      type: "spring",
      duration: 0.5,
      bounce: 0.5,
      delayChildren: 0.5,
      staggerChildren: 0.3,
    },
  },
};

const circleVariants = {
  start: {
    scale: 0,
    y: 30,
  },
  end: {
    scale: 1,
    y: 0,
    transition: {
      type: "spring",
      bounce: 0.5,
      duration: 1,
    },
  },
};

// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
  return (
    <Box variants={boxVariants} initial="start" animate="end">
      <Circle variants={circleVariants} />
      <Circle variants={circleVariants} />
      <Circle variants={circleVariants} />
      <Circle variants={circleVariants} />
    </Box>
  );
}

box3

const boxVariants = {
  hover: {
    scale: 1.5,
    rotateZ: 90,
  },
  click: {
    scale: 1,
    borderRadius: "100px",
  },
};

// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
  return <Box variants={boxVariants} whileHover="hover" whileTap="click" />;
}

box4

const boxVariants = {
  drag: { backgroundColor: "rgb(46,203,113)", transition: { duration: 0.5 } },
};

// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
  const biggerBoxRef = useRef<HTMLDivElement>(null);

  return (
    <BigBox ref={biggerBoxRef}>
      <Box
        variants={boxVariants}
        drag
        // dragSnapToOrigin //! 제자리로 돌아오기
        // dragElastic={0.5} //! 관성력 (0~1)
        dragConstraints={biggerBoxRef} //! 제약 공간
        whileDrag="drag" //! drag
      />
    </BigBox>
  );
}

box5

export default function () {
  const { scrollYProgress } = useViewportScroll();
  const x = useMotionValue(0);

  const size = useTransform(scrollYProgress, [0, 1], [2, 0.4]);
  const rotateZ = useTransform(x, [-300, 0, 300], [-720, 0, 720]);
  return (
    <Box>
      <ScrollBox
        style={{ scale: size, rotateZ, x }}
        drag="x"
        dragSnapToOrigin
      />
    </Box>
  );
}

box6

const svg = {
  start: {
    fill: "rgba(255,255,255,0)",
    pathLength: 0,
  },
  end: {
    fill: "rgba(0,0,0,1)",
    pathLength: 1,
  },
};
// ! 일괄 적용하고 싶으면 variants에 transition적용
// ! 개별 적용하고 싶으면 transition prop로 적용

// eslint-disable-next-line import/no-anonymous-default-export
export default function () {
  return (
    <Box>
      <MySvg
        focusable="false"
        data-icon="linux"
        xmlns="http://www.w3.org/2000/svg"
        viewBox="0 0 488 512"
      >
        <motion.path
          variants={svg}
          initial={"start"}
          animate={"end"}
          transition={{
            default: { duration: 3 },
            fill: { duration: 1, delay: 3 },
          }}
          d="M220.8 123.3c1 .5 1.8 1.7 3 1.7 1.1 0 2.8-.4 2.9-1.5.2-1.4-1.9-2.3-3.2-2.9-1.7-.7-3.9-1-5.5-.1-.4.2-.8.7-.6 1.1.3 1.3 2.3 1.1 3.4 1.7zm-21.9 1.7c1.2 0 2-1.2 3-1.7 1.1-.6 3.1-.4 3.5-1.6.2-.4-.2-.9-.6-1.1-1.6-.9-3.8-.6-5.5.1-1.3.6-3.4 1.5-3.2 2.9.1 1 1.8 1.5 2.8 1.4zM420 403.8c-3.6-4-5.3-11.6-7.2-19.7-1.8-8.1-3.9-16.8-10.5-22.4-1.3-1.1-2.6-2.1-4-2.9-1.3-.8-2.7-1.5-4.1-2 9.2-27.3 5.6-54.5-3.7-79.1-11.4-30.1-31.3-56.4-46.5-74.4-17.1-21.5-33.7-41.9-33.4-72C311.1 85.4 315.7.1 234.8 0 132.4-.2 158 103.4 156.9 135.2c-1.7 23.4-6.4 41.8-22.5 64.7-18.9 22.5-45.5 58.8-58.1 96.7-6 17.9-8.8 36.1-6.2 53.3-6.5 5.8-11.4 14.7-16.6 20.2-4.2 4.3-10.3 5.9-17 8.3s-14 6-18.5 14.5c-2.1 3.9-2.8 8.1-2.8 12.4 0 3.9.6 7.9 1.2 11.8 1.2 8.1 2.5 15.7.8 20.8-5.2 14.4-5.9 24.4-2.2 31.7 3.8 7.3 11.4 10.5 20.1 12.3 17.3 3.6 40.8 2.7 59.3 12.5 19.8 10.4 39.9 14.1 55.9 10.4 11.6-2.6 21.1-9.6 25.9-20.2 12.5-.1 26.3-5.4 48.3-6.6 14.9-1.2 33.6 5.3 55.1 4.1.6 2.3 1.4 4.6 2.5 6.7v.1c8.3 16.7 23.8 24.3 40.3 23 16.6-1.3 34.1-11 48.3-27.9 13.6-16.4 36-23.2 50.9-32.2 7.4-4.5 13.4-10.1 13.9-18.3.4-8.2-4.4-17.3-15.5-29.7zM223.7 87.3c9.8-22.2 34.2-21.8 44-.4 6.5 14.2 3.6 30.9-4.3 40.4-1.6-.8-5.9-2.6-12.6-4.9 1.1-1.2 3.1-2.7 3.9-4.6 4.8-11.8-.2-27-9.1-27.3-7.3-.5-13.9 10.8-11.8 23-4.1-2-9.4-3.5-13-4.4-1-6.9-.3-14.6 2.9-21.8zM183 75.8c10.1 0 20.8 14.2 19.1 33.5-3.5 1-7.1 2.5-10.2 4.6 1.2-8.9-3.3-20.1-9.6-19.6-8.4.7-9.8 21.2-1.8 28.1 1 .8 1.9-.2-5.9 5.5-15.6-14.6-10.5-52.1 8.4-52.1zm-13.6 60.7c6.2-4.6 13.6-10 14.1-10.5 4.7-4.4 13.5-14.2 27.9-14.2 7.1 0 15.6 2.3 25.9 8.9 6.3 4.1 11.3 4.4 22.6 9.3 8.4 3.5 13.7 9.7 10.5 18.2-2.6 7.1-11 14.4-22.7 18.1-11.1 3.6-19.8 16-38.2 14.9-3.9-.2-7-1-9.6-2.1-8-3.5-12.2-10.4-20-15-8.6-4.8-13.2-10.4-14.7-15.3-1.4-4.9 0-9 4.2-12.3zm3.3 334c-2.7 35.1-43.9 34.4-75.3 18-29.9-15.8-68.6-6.5-76.5-21.9-2.4-4.7-2.4-12.7 2.6-26.4v-.2c2.4-7.6.6-16-.6-23.9-1.2-7.8-1.8-15 .9-20 3.5-6.7 8.5-9.1 14.8-11.3 10.3-3.7 11.8-3.4 19.6-9.9 5.5-5.7 9.5-12.9 14.3-18 5.1-5.5 10-8.1 17.7-6.9 8.1 1.2 15.1 6.8 21.9 16l19.6 35.6c9.5 19.9 43.1 48.4 41 68.9zm-1.4-25.9c-4.1-6.6-9.6-13.6-14.4-19.6 7.1 0 14.2-2.2 16.7-8.9 2.3-6.2 0-14.9-7.4-24.9-13.5-18.2-38.3-32.5-38.3-32.5-13.5-8.4-21.1-18.7-24.6-29.9s-3-23.3-.3-35.2c5.2-22.9 18.6-45.2 27.2-59.2 2.3-1.7.8 3.2-8.7 20.8-8.5 16.1-24.4 53.3-2.6 82.4.6-20.7 5.5-41.8 13.8-61.5 12-27.4 37.3-74.9 39.3-112.7 1.1.8 4.6 3.2 6.2 4.1 4.6 2.7 8.1 6.7 12.6 10.3 12.4 10 28.5 9.2 42.4 1.2 6.2-3.5 11.2-7.5 15.9-9 9.9-3.1 17.8-8.6 22.3-15 7.7 30.4 25.7 74.3 37.2 95.7 6.1 11.4 18.3 35.5 23.6 64.6 3.3-.1 7 .4 10.9 1.4 13.8-35.7-11.7-74.2-23.3-84.9-4.7-4.6-4.9-6.6-2.6-6.5 12.6 11.2 29.2 33.7 35.2 59 2.8 11.6 3.3 23.7.4 35.7 16.4 6.8 35.9 17.9 30.7 34.8-2.2-.1-3.2 0-4.2 0 3.2-10.1-3.9-17.6-22.8-26.1-19.6-8.6-36-8.6-38.3 12.5-12.1 4.2-18.3 14.7-21.4 27.3-2.8 11.2-3.6 24.7-4.4 39.9-.5 7.7-3.6 18-6.8 29-32.1 22.9-76.7 32.9-114.3 7.2zm257.4-11.5c-.9 16.8-41.2 19.9-63.2 46.5-13.2 15.7-29.4 24.4-43.6 25.5s-26.5-4.8-33.7-19.3c-4.7-11.1-2.4-23.1 1.1-36.3 3.7-14.2 9.2-28.8 9.9-40.6.8-15.2 1.7-28.5 4.2-38.7 2.6-10.3 6.6-17.2 13.7-21.1.3-.2.7-.3 1-.5.8 13.2 7.3 26.6 18.8 29.5 12.6 3.3 30.7-7.5 38.4-16.3 9-.3 15.7-.9 22.6 5.1 9.9 8.5 7.1 30.3 17.1 41.6 10.6 11.6 14 19.5 13.7 24.6zM173.3 148.7c2 1.9 4.7 4.5 8 7.1 6.6 5.2 15.8 10.6 27.3 10.6 11.6 0 22.5-5.9 31.8-10.8 4.9-2.6 10.9-7 14.8-10.4s5.9-6.3 3.1-6.6-2.6 2.6-6 5.1c-4.4 3.2-9.7 7.4-13.9 9.8-7.4 4.2-19.5 10.2-29.9 10.2s-18.7-4.8-24.9-9.7c-3.1-2.5-5.7-5-7.7-6.9-1.5-1.4-1.9-4.6-4.3-4.9-1.4-.1-1.8 3.7 1.7 6.5z"
        ></motion.path>
      </MySvg>
    </Box>
  );
}

(참고 : https://fontawesome.com/ 에서 svg 파일 복사)

로 demo를 만들어보았다!! (동영상 못올리는거 킹받네;;;)

내일 slider 만드는 거까지 배우면 웬만큼 이쁜 애니메이션 기능은 다 넣을 수 있을 것 같다ㅜㅜ 2월에 만들 내 페이지 기대가 되는고만ㅎㅎ

ps.
백신 3차맞고 골골되다가 주말이 갔다,,,, 내일부터 다시 정신차리고 계획세워서 영어부터 코딩까지 착실하게 시작해야겠다!! 내일 면접 잘 보고!!!!!!!
새로운 마음가짐으로 다시 시작하자!!

profile
과정을 적는 곳

0개의 댓글