카테고리 없음

[motion] 정답(동그라미) 애니메이션 구현 방법

순코딩 2025. 4. 23. 11:02

미리보기

 

 

 

설치

npm install motion/react
npm install @mui/material

 

코드

// 라이브러리 임포트
import { motion } from "motion/react";
import { styled } from "@mui/material";

// 컴포넌트 정의
const AnimatedCircle = () => {
  const draw = {
    hidden: { rotate: 90, pathLength: 0, opacity: 0 },
    visible: {
      pathLength: 1,
      opacity: 1,
      transition: {
        pathLength: { type: "spring", duration: 1.5, bounce: 0 },
        opacity: { duration: 0.01 },
      },
    },
  };

  const boxSize = 80;

  return (
    <AnimatedCircleContainer
      width={boxSize}
      height={boxSize}
      viewBox={`0 0 ${boxSize} ${boxSize}`}
      initial="hidden"
      animate="visible"
    >
      <CirclePath cx={boxSize / 2} cy={boxSize / 2} r={30} variants={draw} />
    </AnimatedCircleContainer>
  );
};

// 스타일 컴포넌트 정의
const AnimatedCircleContainer = styled(motion.svg)`
  position: absolute;
  right: -40px;
  top: -40px;
`;

const CirclePath = styled(motion.circle)`
  stroke: ${({ theme }) => theme.palette.info.main};
  stroke-width: 10px;
  stroke-linecap: round;
  fill: ${({ theme }) => theme.palette.background.paper};
`;

 

 

참고자료

https://motion.dev/docs/react-animation#animatable-values

 

React animation | Motion for React (prev Framer Motion)

Learn how to animate with Motion for React. Discover springs, exit animations, layout animations, scroll animations and more.

motion.dev

 

추가

//////////////////// 엑스(오답) 애니메이션 ////////////////////
const AnimatedX = () => {
  const draw = {
    hidden: { pathLength: 0, opacity: 0 },
    visible: (i: number) => {
      const delay = i * 0.2;
      return {
        pathLength: 1,
        opacity: 1,
        transition: {
          pathLength: { delay, type: "spring", duration: 0.3, bounce: 0 },
          opacity: { delay, duration: 0.01 },
        },
      };
    },
  };

  const boxSize = 80;
  const line1 = {
    start: [20, 20],
    end: [60, 60],
  };

  const line2 = {
    start: [60, 20],
    end: [20, 60],
  };

  return (
    <AnimatedXContainer
      width={boxSize}
      height={boxSize}
      viewBox={`0 0 ${boxSize} ${boxSize}`}
      initial="hidden"
      animate="visible"
    >
      {/* 20,20 -> 60,60 */}
      <XPath1 x1={line1.start[0]} y1={line1.start[1]} x2={line1.end[0]} y2={line1.end[1]} variants={draw} custom={1} />
      {/* 60,20 -> 20,60 */}
      <XPath2
        x1={line2.start[0]}
        y1={line2.start[1]}
        x2={line2.end[0]}
        y2={line2.end[1]}
        variants={draw}
        custom={1.5}
      />
    </AnimatedXContainer>
  );
};