Lottie와 Framer를 활용한 React 애니메이션 구현

woodylovesboota·2023년 12월 18일
0
post-thumbnail

Lottie player 는 웹 및 모바일 환경에서 vector animation을 표시하기 위한 라이브러리 중 하나로 이를 이용하여 비교적 간단하게 웹에서 애니메이션을 재생할 수 있다.

Lottie Player 애니메이션

lottiefiles 에서 다양한 애니메이션을 찾아볼 수 있다. 직접 만드는 것도 가능하지만 홈페이지에서 무료로 제공하는 애니메이션을 사용하는 것도 방법이다.

React에서Lottie 사용하기

react-lottie 를 이용하면 react 환경에서 편하게 Lottie를 사용할 수 있다.

$ npm install --save react-lottie

이후 .json 확장자로 된 lottie file을 react project의 src 폴더에 가져온다.

// src/animationData.json
{
  "v": "4.8.0",
  "meta": {
    "g": "LottieFiles AE 3.5.2",
    "a": "",
    "k": "",
    "d": "",
    "tc": ""
  },
  "fr": 60,
  "ip": 0,
  "op": 180,
  "w": 300,
  "h": 300,
  "nm": "Comp 1",
  "ddd": 0,
  "assets": [ ...

마지막으로 Lottie를 사용하고 싶은 component에서 react-lottie를 이용하여 json 파일을 불러오면 된다.

import Lottie from "react-lottie-player";
import animationData from "../animationData.json";

const App = () => {

  ...
  return <Lottie
      animationData={animationData}
      style={{ width: "200px", height: "200px" }}
      loop
      play
      speed={5}
      />;
};

애니메이션 추가하기

react-lottie를 이용하여 불러온 데이터는 그 자체로 component 이므로 위에서 처럼 style을 지정해 줄 수 있다. 따라서 framer-motion , keyframes 등을 이용하여 추가적인 애니메이션을 적용할 수 있다.

framer-motion

Framer는 매우 자주 사용하는 react library 중 하나이지만 동작 원리를 정확히 알지 못해 이번 기회에 제대로 알고 사용하고 싶었다.

Framer 등 추가적인 애니메이션을 사용하기 위해 Lottie를 div로 한번 더 감싸주었다.

<SheepBox>
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={5}
    />
</SheepBox>

이후 화면 왼쪽 끝에서 오른쪽 끝 까지 양이 이동하게 하는 애니메이션을 추가해주었다.

const sheepVar = {
  initial: { x: -200 },
  animate: { x: "100vw", transition: { duration: 5 } },
};

<SheepBox variants={sheepVar} initial="initial" animate="animate">
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={5}
    />
</SheepBox>

연속된 애니메이션

framer를 이용하여 애니메이션 효과를 주다 보면 무한히 이어지는 효과를 주고싶을 때가 있다. 내가 찾은 방법은 총 두가지 이다.

(1) repeat: Infinity

가장 간단한 방법은 repeat: Infinity 속성을 추가해 주는 것이다.

const sheepVar = {
  initial: { x: -200 },
  animate: { x: "100vw", transition: { duration: 5, repeat: Infinity } },
};

이 방법은 간단하게 애니메이션을 무한히 실행시킬 수 있는 방법이다. 하지만 반복에 대한 세부적인 조건을 설정하지 못하는 등 불편한 점이 없는 것은 아니라고 생각한다. 따라서 단순한 하나의 애니메이션을 반복할 때 사용하면 좋은 방법이라고 생각한다.

(2) key 이용

두번째 방법은 component의 key를 이용하는 방법이다. React에서는 당연하게도 서로 key가 다른 component를 다른 component라고 인식한다. 따라서 일정 주기마다 key값이 다른 component를 생성해주면 특정 애니메이션을 무한히 반복할 수 있다.

  const [sheepCount, setSheepCount] = useState(1);

  useEffect(() => {
    const timer2 = setInterval(() => {
      setSheepCount(sheepCount + 1);
    }, 7000);
  });


<SheepBox key={sheepCount} variants={sheepVar} initial="initial" animate="animate">
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={2}
    />
</SheepBox>

이를 이용하면 주기적으로 count를 증가시켜 일정 시간마다 새로운 양이 출발점에서 끝점까지 이동하는 애니메이션을 구현할 수 있다.

경험 상 위 방법이 AnimatePresence를 이용하는 경우(exit 등)에 (1) repeat:Infinity 보다 이어지는 애니메이션을 좀 더 쉽게 구현할 수 있었다.

또한 전체 애니메이션의 시작 / 종료 시점을 한번에 설정할 수 있어 다수의 애니메이션의 주기를 한번에 설정하는데 좀 더 유리한 방법이다.

동시 애니메이션

만약 양 5마리를 동시에 시작점에서 끝점까지 이동시키고 싶다면 어떻게 해야할 까?

속도가 서로 다른 양 5마리가 제각각 다른 주기를 가지고 시작점과 끝점을 이동하고 싶다면 repeat: Infinity 방식이 좀 더 편한 방법일 것이다.

const sheepSecondVar = {
  initial: { x: -500 },
  animate: { x: "100vw", transition: { duration: 7, delay: 2, repeat: Infinity } },
};

const sheepThirdVar = {
  initial: { x: -500 },
  animate: { x: "100vw", transition: { duration: 8, delay: 4, repeat: Infinity } },
};

이렇게 구현할 경우 각 양들이 자신의 주기를 가지고 따로따로 출발하는 것을 확인할 수 있다.

하지만 출발한 양들이 도착한 후 다른 양들을 기다리고 또 다시 한번에 출발하고 싶을 때는 위 방법은 좋은 방법이 되지 못한다. repeat: Infinity를 이용하였다면 각 양의 duration과 delay를 계산하여서 repeat delay를 추가적으로 설정해주어야 한다.

이때는 key를 이용하는 것이 더 효과적인 방법일 것이다.

  <SheepBox key={sheepCount + "first"} variants={sheepVar} initial="initial" animate="animate">
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={2}
    />
</SheepBox>
<SheepBox key={sheepCount + "second"} variants={sheep2Var} initial="initial" animate="animate">
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={2}
    />
</SheepBox>
<SheepBox key={sheepCount + "third"} variants={sheep3Var} initial="initial" animate="animate">
  <Lottie
    animationData={animationData}
    style={{ width: "200px", height: "200px", transform: "rotateY(180deg)" }}
    loop
    play
    speed={2}
    />
</SheepBox>

모든 양이 같은 주기를 가지고 시작점과 끝점을 이동하는 것을 확인할 수 있다.

0개의 댓글