Framer Motion: useMotionValue와 useSpring의 차이점 및 활용 예제

송연지·2024년 12월 18일
0
post-thumbnail

Framer Motion 소개

업로드중..

Framer Motion은 React 애니메이션 라이브러리로, 간단하고 직관적인 방식으로 동적 애니메이션을 구현할 수 있습니다. 특히 motion, useMotionValue, useSpring, useTransform 같은 훅과 컴포넌트를 제공하여 강력한 애니메이션 제어가 가능합니다.

useMotionValue와 useSpring의 차이점

useMotionValue와 useSpring 모두 값을 변경하는 데 사용되지만, 동작 메커니즘이 다릅니다.

1. useMotionValue

  • 즉각적인 값 변경
    값을 변경(set())하면 애니메이션 없이 해당 값으로 바로 전환됩니다.
    예: y.set(100) → 값이 즉시 100으로 설정됨.

  • 애니메이션 제어 없음
    부드러운 전환 효과를 추가하려면 별도의 트랜지션이 필요합니다.


2. useSpring

  • 스프링 애니메이션
    값을 변경(set())하면 스프링 물리 모델에 따라 부드럽게 전환됩니다.
    예: y.set(100) → 스프링 감쇠와 가속/감속 효과를 통해 자연스러운 애니메이션이 발생.

  • 파라미터로 제어 가능
    damping, stiffness 등을 통해 애니메이션 속도와 부드러움을 조절할 수 있습니다.


useMotionValue vs useSpring 비교 결과

특성useMotionValueuseSpring
값 변경 속도즉각적부드러운 전환 (스프링 물리 효과)
애니메이션 설정별도 설정 필요기본적으로 자연스러운 애니메이션
사용자 경험(UX)다소 딱딱한 이동자연스러운 전환

실습 예제: 스크롤 애니메이션 구현

아래는 스크롤 진행도에 따라 텍스트가 위로 이동하며 나타나는 애니메이션을 구현한 예제입니다.
useMotionValueuseSpring을 각각 적용한 경우를 비교해 보겠습니다.

코드 1: useSpring을 사용하는 예제

"use client";

import {
  motion,
  useScroll,
  useTransform,
  useSpring,
} from "framer-motion";
import { useEffect } from "react";

export default function Page() {
  // 스프링 애니메이션으로 부드러운 값 제어
  const smoothY = useSpring(0, {
    damping: 15, // 감쇠 강도
  });

  const { scrollYProgress } = useScroll({
    offset: ["start start", "end end"],
  });

  useEffect(() => {
    return scrollYProgress.on("change", (latest) => {
      // 스크롤 값이 바뀔 때마다 스프링 값 업데이트
      smoothY.set(latest);
    });
  }, [scrollYProgress, smoothY]);

  // 스크롤 진행도에 따라 텍스트의 Y 위치와 투명도 조절
  const textY = useTransform(scrollYProgress, [0.7, 0.75], ["100%", "0%"]);

  return (
    <div className="relative w-full h-[3000px]">
      <div className="fixed inset-0 flex items-center justify-center">
        <motion.div
          className="bg-orange-400"
          style={{
            position: "absolute",
            inset: 0,
            clipPath: useTransform(scrollYProgress, (value) => `circle(${value * 100}%)`),
          }}
        >
          <div className="h-full flex flex-col p-5 items-start justify-start text-blue-600 text-4xl font-bold overflow-hidden">
            {/* 텍스트 애니메이션 */}
            <div className="overflow-hidden h-[40px] mb-2">
              <motion.div
                style={{ y: textY }}
                transition={{ duration: 1.2 }}
              >
                <div>Aha!</div>
              </motion.div>
            </div>
            <div className="overflow-hidden h-[40px]">
              <motion.div
                style={{ y: textY }}
                transition={{ duration: 1.2 }}
              >
                <div>You found me!</div>
              </motion.div>
            </div>
          </div>
        </motion.div>
      </div>
    </div>
  );
}

코드 2: useMotionValue를 사용하는 예제

"use client";

import {
  motion,
  useScroll,
  useTransform,
  useMotionValue,
} from "framer-motion";
import { useEffect } from "react";

export default function Page() {
  // 스크롤 값을 관리하는 motionValue
  const smoothY = useMotionValue(0);

  // 스크롤 진행도를 감지하는 useScroll
  const { scrollYProgress } = useScroll({
    offset: ["start start", "end end"],
  });

  useEffect(() => {
    return scrollYProgress.on("change", (latest) => {
      // 스크롤 값이 바뀔 때 즉각적으로 값을 설정
      smoothY.set(latest); // 즉각적인 값 변경
    });
  }, [scrollYProgress, smoothY]);

  return (
    <div className="relative w-full h-[3000px]">
      <div className="fixed inset-0 flex items-center justify-center">
        <motion.div
          className="bg-orange-400"
          style={{
            clipPath: useTransform(smoothY, (value) => `circle(${value * 100}%)`),
          }}
        >
          <div className="h-full flex flex-col text-blue-600 text-4xl font-bold">
            <motion.div style={{ y: textY }}>Aha!</motion.div>
            <motion.div style={{ y: textY }}>You found me!</motion.div>
          </div>
        </motion.div>
      </div>
    </div>
  );
}

주요 코드 설명

  • useSpring으로 부드러운 애니메이션 구현
const smoothY = useSpring(0, {
  damping: 15,//스크롤 진행 값을 useSpring으로 처리하여 부드러운 애니메이션 효과를 적용했습니다
});
  • 스크롤 위치 감지
const { scrollYProgress } = useScroll({
  offset: ["start start", "end end"],//스크롤 위치를 감지하고 scrollYProgress를 활용해 값을 업데이트합니다.
});
  • 텍스트 애니메이션
//스크롤 진행도에 따라 텍스트가 아래에서 위로 이동하도록 useTransform으로 값을 변환합니다.
const textY = useTransform(scrollYProgress, [0.7, 0.75], ["100%", "0%"]);
  • 클립 패스 애니메이션
//clip-path 속성을 이용해 스크롤 진행에 따라 화면이 원형으로 드러나는 효과를 추가했습니다.
clipPath: useTransform(scrollYProgress, (value) => `circle(${value * 100}%)`),

결론

  • useSpring을 사용하면 애니메이션의 부드러움과 자연스러운 동작을 추가할 수 있습니다.
  • motionValue는 애니메이션 없이 값을 빠르게 업데이트해야 할 때 유용하지만, 사용자 경험 측면에서는 덜 부드러울 수 있습니다.

따라서, 애니메이션이 필요한 경우에는 useSpring을 사용하는 것을 권장합니다.

profile
프론트엔드 개발쟈!!

0개의 댓글