はじめに
ここでは、Next.js(App Router)において、framer-motionを用いてページ遷移時にアニメーションを実装する方法について解説しようと思います。
ここではWebアプリを想定し、ページにダイレクトされた際にアニメーションでフェードする方法をなるべく優しく書きます。
目的
- ページ遷移時に遷移後ページがアニメーション付きで表示される。
-
framer-motionのAnimatePresenceの活用 - App Router (
app/) 構成で動作 - template も活用。
使用技術
- Next.js (App Router)
- framer-motion
- React
- TS
template.tsx を活用する理由
App Routerには以下の特徴があります。
-
layout.tsx→ ページ遷移しても再マウントされない -
template.tsx→ ページ遷移ごとに再マウントされる
→ページ遷移アニメーションをさせたい場合は template.tsx を活用すると吉。
ディレクトリ構成例
app/
├─ template.tsx
├─ page.tsx
components/
└─ layout/
└─ PageTransition.tsx // 遷移時のアニメーションを実装
template.tsx の実装
import { PageTransition } from "@/components/layout/PageTransition";
export default function Template({
children,
}: {
children: React.ReactNode;
}) {
return <PageTransition>{children}</PageTransition>;
}
ポイント
- ここでの
template.tsxはすべてのページをラップする役割 -
childrenに各ページの内容が入る - 実際のアニメーションのロジックはコンポーネントを分離したほうがいい。
- この後に書く
PageTransitionコンポーネントでラップすることで、すべてに適用
PageTransition コンポーネント
"use client";
import { motion, AnimatePresence } from "framer-motion";
import { usePathname } from "next/navigation";
export function PageTransition({
children,
}: {
children: React.ReactNode;
}) {
const pathname = usePathname();
return (
<AnimatePresence mode="wait">
<motion.div
key={pathname}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
transition={{ duration: 0.3, ease: "easeInOut" }}
className="flex-grow flex flex-col"
>
{children}
</motion.div>
</AnimatePresence>
);
}
ポイント
-
usePathname()を key に使うことで、別コンポーネントとして再生成
const pathname = usePathname();
<motion.div key={pathname}>
-
keyが変わるとは別コンポーネントとして再生成
→ 遷移時に pathname が都度変更
アニメーションが発火
-
AnimatePresenceの役割
<AnimatePresence mode="wait">
-
mode="wait"により、遷移元のがunmountが終わってから遷移先のmountが始まる
→ ページの移り変わりが自然になる。
- アニメーション定義
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: -20 }}
| 状態 | 内容 |
|---|---|
| initial | アニメーション発火時の状態 |
| animate | 通常時の表示 |
| exit | uhnmountするときの状態 |
transition={{ duration: 0.3, ease: "easeInOut" }}
| 状態 | 内容 |
|---|---|
| duration | アニメーションンにかかる時間の長さ |
| ease | アニメーションの速度カーブ |
まとめ
ここまででの解説にある通り、 App Router でページ遷移時のアニメーションを入れるなら、
template.tsxAnimatePresence-
key={pathname}
の3つの実装を行うことで、簡単に実装できます。