[React] 페이지 이동시 애니메이션 효과 적용하기 (feat. framer motion)

2022. 9. 24. 10:04React

728x90

Framer-motion을 통해서 컴포넌트에 등장 애니메이션 적용한 저번 포스트에 이어서 이번 포스트에서는 페이지 이동시 자연스럽게 전환되도록 애니메이션 효과를 적용해보도록 하겠습니다.

 

react-transition-group 같은 패키지를 사용해도 무방하지만 저번 포스트에서 framer-motion으로 진행했기 때문에 같은 라이브러리를 사용해서 진행해 보겠습니다.

 

부드러운 page transition 효과가 적용된 상태 (예전에 진행했던 프로젝트)

 

 

우선 framer-motion이 설치되있지 않은 분들은 아래 명령어를 통해 설치해주시길 바랍니다.

 

npm i framer-motion // 또는 yarn

Animate Presence 로 애니메이션 적용하기

페이지간의 자연스러운 이동을 위해서는 Framer에서 제공하는 AnimatePresence라는 컴포넌트를 사용해야합니다. 해당 컴포넌트를 사용하게 되면 특정 요소가 사라지기 전에 지정한 애니메이션 효과를 줄 수 있습니다. 모든 페이지에 이펙트가 적용될 수 있도록 아래와 같이 라우터를 설정하는 부분을 해당 컴포넌트로 감싸주도록 하겠습니다.

 

App.js

 import { Switch, Route } from 'react-router';
 import { AnimatePresence } from 'framer-motion';
 import { Home, Notice, NotFound } from 'pages';
 
 
 const App = () => {
 /* 생략 */
 return (
     <div className="app">
          <AnimatePresence>
            <Switch>
               <Route exact path="/" component={Home} />
              <Route exact path="/terms/use" component={Notice} />
              <Route path="*" component={NotFound} />
            </Switch>
          </AnimatePresence>
        </div>
    )
 }
 
 export default App;

 

이제 페이지의 등장, 퇴장 애니메이션을 정의하기 위해서 framer에서 제공하는 motion.div 태그를 사용해보겠습니다. 페이지마다 다른 이펙트를 주고 싶다면 props로 받아서 지정해줘도 되지만 해당 예제에서는 고정으로 사용할 것이기 때문에 아래와 같이 컴포넌트를 만들었습니다.

 

components/Wrapper.js

import React from 'react';
import { motion } from 'framer-motion';
import { pageEffect } from 'styles/animation';

const Wrapper = ({ children, ...rest }) => {
  return (
    <motion.div
      initial="initial"
      animate="in"
      exit="out"
      transition={{ duration: 0.5 }}
      variants={pageEffect}
      {...rest}
    >
      {children}
    </motion.div>
  );
};

export default Wrapper;

 

variants에 들어가는 애니메이션에 대한 정의는 styles 또는 별도의 폴더에 따로 저장해 재사용하는걸 추천드립니다. 필자는 pageEffect라고 이름을 지은 뒤 초기 상태를 initial, 등장 상태를 in, 퇴장 상태를 out으로 지정한 뒤, 각 상태에서 투명도만 조절하도록 설정했습니다. 좀 더 화려한 이펙트를 원하시는 분들은 이 부분을 opacity가 아닌 희망하는 css 효과로 지정해주시면 됩니다.

 

styles/animation.js

export const pageEffect = {
  initial: {
    opacity: 0
  },
  in: {
    opacity: 1
  },
  out: {
    opacity: 0
  }
};

 

이제 해당 이펙트를 적용하고자 하는 페이지를 Wrapper 컴포넌트로 감싸주시기만 하면 됩니다.

 

Notice.js

import Wrapper from 'components/Wrapper';

const Notice = () => {
 /*생략*/
  return (
    <Wrapper>
     {/* 생략 */}
    </Wrapper>
  );
};

export default Notice;

 

아래와 같이 varaints만 변경해주면 여러가지 이펙트를 줄 수 있으니 다양하게 시도해보신 후,

현재 진행하고 계신 프로젝트에 제일 알맞는 효과를 찾아보시길 바랍니다.

 

transition type spring 효과를 준 결과

 

참고자료:

 

AnimatePresence | Framer for Developers

Animate components when they're removed from the React tree.

www.framer.com