1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

framer-motion を使った Next.js でのページ遷移時のアニメーション実装解説

1
Posted at

はじめに

ここでは、Next.js(App Router)において、framer-motionを用いてページ遷移時にアニメーションを実装する方法について解説しようと思います。

ここではWebアプリを想定し、ページにダイレクトされた際にアニメーションでフェードする方法をなるべく優しく書きます。


目的

  • ページ遷移時に遷移後ページがアニメーション付きで表示される。
  • framer-motionAnimatePresenceの活用
  • 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.tsx
  • AnimatePresence
  • key={pathname}
    の3つの実装を行うことで、簡単に実装できます。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?