라이브러리 없이 animation을 적용하려면 요소가 랜더링 되어있어야 하고, trigger가 있어야 한다.
그런 점에서, 페이지 전환 같은 효과는 라이브러리 없이 만들기 힘들다.
개인적으로 진행한 다이어리&스케줄러 프로젝트에서 Framer-motion을 페이지 전환 시 애니메이션 적용을 위해 유용하게 사용하였다.
Outlet
을 AnimatePresence
로 감쌌다.// Home.tsx
import { AnimatePresence } from "framer-motion";
import { Outlet } from "react-router-dom";
...
<footer>
...
<AnimatePresence>
<Outlet /> /* Login, Register */
</AnimatePresence>
</footer>
...
하위 페이지 애니메이션 적용
// Login.tsx
import { motion } from "framer-motion";
...
<motion.form
initial={{ x: 300, opacity: 0 }}
animate={{ x: 0, opacity: 1, transition: { duration: 0.5 } }}
>
...
/* 로그인, 회원가입 */
</motion.form>
animation 적용을 위한 attribute들은 직관적인 이름이라 이해하기 쉬웠다. 공식문서에 예시와 예시 UI까지 나와있어서, 마음에 드는 애니메이션 효과를 보고 참고해서 사용하면 된다.
initial
: 초기에 적용하고 싶은 것들을 넣으면 됨. 위치, 설정하고 싶은 요소들을 적용하면 됨. 랜더링 된 직후에 바로 실행animate
: initial
다음에 실행됨. 위 구현 결과는 position으로 만들어지는 걸까? 궁금해서 검사창으로 확인해보니, x
속성은 transform: translateX(300px)
로 적용되어 있었다.
그리고, 애니메이션이 실행되고 transform: none
으로 변경되는 것을 볼 수 있었다.
button
을 통해 페이지 이동시,button
이 확대되며 페이지가 나타남- 다시 원래 페이지로 이동 시, 화면이 축소되며
button
으로 연결되어(?) 사라지는 효과- layoutId 속성을 통해 동일한 id를 가진 다른 페이지의 요소와 연결하여 애니메이션 적용
// Scheduler.tsx -> button이 있는 본 페이지
import { AnimatePresence, motion } from "framer-motion";
...
<motion.button
/* layoutId 속성을 통해 다른 페이지의 동일 id를 가진 요소와 연결 */
layoutId="addPage"
onClick={() => navigate("/scheduler/add")}
>
<IconPlus />
</motion.button>
// Add.tsx -> button을 통해 이동한 페이지
// id로 연결할 요소는 motion 사용하지 않아도 됨
<section> /* Overlay - 검은색 바탕 */
<div id="addForm">
/*... inputs, buttons */
</div>
</section>