5월부터 시작한 사이드 프로젝트가 어느정도 마무리 단계에 접어들면서 개선할 부분을 찾아보다가 문득 화면 전환이 부드러워졌으면 좋겠다는 생각이 들었다.
그래서, 찾아본 몇 가지 방법들은 아래와 같다.
motion-framer
라이브러리 사용react-transition-group
라이브러리 사용이 중에서 나는 2. react-transition-group
라이브러리를 사용하기로 하였다.
공식 문서 페이지에 따르면 React Transition Group 은 React-Motion 과 같은 애니메이션 라이브러리가 아니면 자체적으로 스타일을 애니메이션화하지 않는다고 한다. 대신 전환 단계를 노출하고 클래스 및 그룹 요소를 관리하여 유용한 방식으로 DOM 을 조작하여 실제 전환 효과 구현을 쉽게 만들 수 있도록 해준다고 한다.
npm install react-transition-group --save
yarn add react-transition-group
화면 전환 효과를 적용할 페이지 컴포넌트를 <TransitionGroup/>
및 <Transition/>
으로 감싸주어야 한다.
나는 Next.js 환경에 react transition group을 적용할 것이기 때문에 /components/layout.tsx
에 적용하였다.
스타일 관련 설정
// /components/layout.tsx
const TIMEOUT = 100; // 전환 소요 시간 (ms)
const getTransitionStyles = {
entering: { // status: 전환 중
position: 'absolute',
opacity: 0
},
entered: { // status: 전환 완료
transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
opacity: 1
},
exiting: { // status: 전환 시작
transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
opacity: 0
}
};
const Layout = ({ children }: IProps) => {...}
Transition 컴포넌트 적용하기
// /components/layout.tsx
import React, { ReactNode } from 'react';
import Header from './header';
import { useRouter } from 'next/router';
import { TransitionGroup, Transition } from 'react-transition-group';
interface IProps {
children: ReactNode;
}
const TIMEOUT = 150;
const getTransitionStyles = {
entering: {
position: 'absolute',
opacity: 0
},
entered: {
transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
opacity: 1
},
exiting: {
transition: `opacity ${TIMEOUT}ms ease-in-out, transform ${TIMEOUT}ms ease-in-out`,
opacity: 0
}
};
const Layout = ({ children }: IProps) => {
const router = useRouter();
return (
<div className='relative h-[100%]'>
<Header />
+ <TransitionGroup style={{ position: 'relative' }}>
+ <Transition
key={router.pathname}
timeout={{
enter: TIMEOUT,
exit: TIMEOUT
}}>
+ {(status) => (
+ <div
style={{
...getTransitionStyles[status]
}}>
<main>
<div className='h-[100%] w-[100%] p-[2em] '>{children}</div>
</main>
</div>
)}
</Transition>
</TransitionGroup>
</div>
);
};
export default Layout;
<Header/>
영역은 전환 효과를 주고 싶지 않았기 때문에, 페이지 컨텐츠 영역인 <main>...</main>
부분만 <Transition/>
으로 감싸주었다.
적용 전
적용 후