framer-motion

ha·2022년 7월 19일
0

framer-motion

목록 보기
1/1
post-thumbnail

기본 사용 방법

function App() {
  return (
    <Wrapper>
      <Box
        transition={{type:"spring",delay:0.5}}
        initial={{scale:0}}
        animate={{scale:1, rotateZ:360}}
      />
    </Wrapper>
  );
}

object 사용

const myVars = {
  start: { scale: 0 },
  end:{scale:1, rotateZ:360, transition:{type:"spring",delay:0.5}}
}

  • 부모요소 initialanimate 자식요소에 그대로 적용됨
  • staggerChildren으로 자식 요소 개별 등장 타이밍 조정 가능
const boxVariants = {
  start: {
    opacity: 0,
    scale: 0.5
  },
  end: {
    scale: 1,
    opacity: 1,
    transition: {
      type: "spring",
      duration: 0.5,
      bounce: 0.5,
      delayChildren: 0.5,
      staggerChildren: 0.2,
    },
  },
};

const circleVariants = {
  start: {
    opacity: 0,
    y: 10,
  },
  end: {
    opacity: 1,
    y: 0,
  },
};
function App() {
  return (
    <Wrapper>
      <Box variants={boxVariants} initial="start" animate="end">
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
        <Circle variants={circleVariants}/>
      </Box>
      
    </Wrapper>
  );
}

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

function App() {
  return (
    <Wrapper>
      <Box 
        variants={boxVariants}
        whileHover="hover"
        whileTap="click"
      />
    </Wrapper>
  );
}


드래그 가능 범위 제한 = dragConstraints,useRef

  • dragSnapToOrigin
  • dragElastic
  • dragConstraints
function App() {
  const biggerBoxRef = useRef<HTMLDivElement>(null);
  return (
    <Wrapper>
      <BiggerBox ref={biggerBoxRef}>
        <Box 
          drag
          dragSnapToOrigin
          dragElastic={0}
          dragConstraints={biggerBoxRef}
          variants={boxVariants}
          whileHover="hover"
          whileTap="click"
      />
      </BiggerBox>
    </Wrapper>
  );
}

useMotioinValue, useTransform 사용 배경화면 전환

  • motionValue로 드래그시 위치 설정
  • useTransform motionvalue값 기준 전환 설정
function App() {
  const x = useMotionValue(0);
  const scale = useTransform(x, [-800, 0, 800], [2, 1, 0.1]);
  const rotateZ = useTransform(x, [-800, 800], [-360, 360]);
  const gradient = useTransform(
    x,
    [-800,0, 800],
    [
      "linear-gradient(135deg, rgb(0, 210, 238), rgb(0, 83, 238))",
      "linear-gradient(135deg, rgb(238, 0, 153), rgb(221, 0, 238))",
      "linear-gradient(135deg, rgb(0, 238, 155), rgb(238, 178, 0))",
    ]
  );
  return (
    <Wrapper style={{background:gradient}}>
      <Box style={{x,scale,rotateZ}} drag="x" dragSnapToOrigin/>
    </Wrapper>
  );
}

useViewportScroll() 스크롤 위치->motionvalue

const { scrollYProgress } = useViewportScroll();
const scale = useTransform(scrollYProgress, [0, 1], [1, 5]);

SVG animation

const Svg = styled.svg`
  widhth:300px;
  height:300px;
  path{
    stroke:white;
    stroke-width:2;
  }
`;

const svg = {
  start: { pathLength: 0, fill: "rgba(255,255,255,0)" },
  end: {
    fill: "rgba(255,255,255,1)",
    pathLength: 1,//line-drawing(percentage)
    transition:{
      default: { duration: 5 },
      fill: { duration: 1, delay: 3 },
    }
  },
};
<Svg
    focusable="false"
    xmlns="http://www.w3.org/2000/svg"
    viewBox="0 0 448 512"
>
    <motion.path
       variants={svg}
       initial="start"
       animate="end"
       d="M224 373.12c-25.24-31.67-40.08-59.43-45-83.18-22.55-88 112.61-88 90.06 0-5.45 24.25-20.29 52-45 83.18zm138.15 73.23c-42.06 18.31-83.67-10.88-119.3-50.47 103.9-130.07 46.11-200-18.85-200-54.92 0-85.16 46.51-73.28 100.5 6.93 29.19 25.23 62.39 54.43 99.5-32.53 36.05-60.55 52.69-85.15 54.92-50 7.43-89.11-41.06-71.3-91.09 15.1-39.16 111.72-231.18 115.87-241.56 15.75-30.07 25.56-57.4 59.38-57.4 32.34 0 43.4 25.94 60.37 59.87 36 70.62 89.35 177.48 114.84 239.09 13.17 33.07-1.37 71.29-37.01 86.64zm47-136.12C280.27 35.93 273.13 32 224 32c-45.52 0-64.87 31.67-84.66 72.79C33.18 317.1 22.89 347.19 22 349.81-3.22 419.14 48.74 480 111.63 480c21.71 0 60.61-6.06 112.37-62.4 58.68 63.78 101.26 62.4 112.37 62.4 62.89.05 114.85-60.86 89.61-130.19.02-3.89-16.82-38.9-16.82-39.58z"
        ></motion.path>
</Svg>

AnimatePresence(variants,initial,animate,exit)

const boxVariants = {
  initial: {
    opacity: 0,
    scale: 0,
  },
  visible: {
    opacity: 1,
    scale: 1,
    rotateZ: 360,
  },
  leaving: {
    opacity: 0,
    scale: 0,
    y: 50,
  },
};

function App() {
  const [showing, setShowing] = useState(false);
  const toggleShowing = () => setShowing((prev) => !prev);
  return (
    <Wrapper>
      <button onClick={toggleShowing}>Click</button>
      <AnimatePresence>
        {showing ? (
          <Box
            variants={boxVariants}
            initial="initial"
            animate="visible"
            exit="leaving"
          />
        ) : null}
      </AnimatePresence>
    </Wrapper>
  );
}

custom(방향 설정), exitBeforeEnter

  • isback ==> box컴포넌트 custom={back}
    const [back,setBack] = useState(false)와 연동되어 사용된다
const box = {
  entry: (isBack:boolean) => ({
  x: isBack ? -500 : 500,
  opacity: 0,
  scale: 0,
  }),
  center: {
  x: 0,
  opacity: 1,
  scale: 1,
  transition: {
  duration: 0.3,
  },
  },
  exit: (isBack:boolean) => ({
  x: isBack ? 500 : -500,
  opacity: 0,
  scale: 0,
  transition: { duration: 0.3 }
  }),
};
function App() {
  const [visible, setVisible] = useState(1);
  const [back,setBack] = useState(false);
  const nextPlease = () => {
  setBack(false);
  setVisible((prev) => (prev === 10 ? 10 : prev + 1));
  }
  const prevPlease = () => {
  setBack(true)
  setVisible((prev) => (prev === 1 ? 1 : prev - 1))
  }
  return (
    <Wrapper>
      <AnimatePresence exitBeforeEnter>
        <Box
          custom={back}
          variants={box}
          initial="entry"
          animate="center"
          exit="exit"
          key={visible}
        >
          {visible}
        </Box>
      </AnimatePresence>
      <button onClick={nextPlease}>next</button>
      <button onClick={prevPlease}>before</button>
    </Wrapper>
  );
}

0개의 댓글