Next.js + Framer Motion でページ遷移アニメーションを実装する
まえがき
React のアニメーションライブラリである Framer Motion を利用してページ遷移アニメーションを実装した際に、いくつか引っかかった点があったので、備忘録として残しておこうと思います。
バージョン
- Next.js v12.1.1
- Framer Motion v6.2.8
今回実装するもの
↑ こんな感じのふんわりしたフェードイン / フェードアウトを実装します。
実際に動いているところは以下のサイトでご覧いただけます…!
手順
1. アンマウント時のアニメーションを有効にする
_app.tsx
import { AnimatePresence } from 'framer-motion'
import type { AppProps } from 'next/app'
import 'styles/globals.css'
const MyApp = ({ Component, pageProps, router }: AppProps) => (
<AnimatePresence exitBeforeEnter>
<Component key={router.asPath} {...pageProps} />
</AnimatePresence>
)
export default MyApp
import { AnimatePresence } from 'framer-motion'
import type { AppProps } from 'next/app'
import 'styles/globals.css'
const MyApp = ({ Component, pageProps, router }: AppProps) => (
<AnimatePresence exitBeforeEnter>
<Component key={router.asPath} {...pageProps} />
</AnimatePresence>
)
export default MyApp
アンマウント時のアニメーションを有効にするため、framer-motion
から <AnimatePresence>
を import して、<Component>
を囲みます。
AnimatePresence
exitBeforeEnter
を設定することで、コンポーネントのアンマウントを待ち、遷移元のアンマウント時のアニメーションと遷移先のマウント時のアニメーションが同時に発生しないようにしています。
Component
key
の値として、初めは router.route
を利用していたのですが、この値は pages/
内でのパスであり Dynamic Routing を使用して生成しているページでは同じ値 (例: works/[id]
) になってしまうため、「該当のページでアニメーションが再生されない」という問題が起きました。
ですので、ここではブラウザ上で表示されるパスである router.asPath
を利用しています。
2. 遷移アニメーションを設定
import { motion } from 'framer-motion'
import type { NextPage } from 'next'
const Hoge = (): NextPage => (
<motion.div
initial={{ opacity: 0 }} // 初期状態
animate={{ opacity: 1 }} // マウント時
exit={{ opacity: 0 }} // アンマウント時
>
// ...
</motion.div>
)
export default Hoge
全体を <motion>
コンポーネントで囲み、任意の遷移アニメーションを設定します。
詳しい Props については、Motion components をご覧ください...。
3. ページ遷移時の挙動を修正
ここまででアニメーション自体は実装できているのですが、スクロールしてからページ遷移を行うと、「アニメーション再生前にページが先頭に戻る」という挙動になってしまいます。
これでは少し不恰好なので、修正していきます。
1. リンクを修正
import Link from 'next/link'
const Fuga = (): JSX.Element => (
<div>
- <Link href="https://example.com/">
+ <Link href="https://example.com/" scroll={false}>
リンク!
</Link>
</div>
)
export default Fuga
ページの遷移が発生する箇所の <Link>
コンポーネントに scroll={false}
を追加して、遷移後の自動スクロールを無効化します。
2. _app.tsxを修正
import { AnimatePresence } from 'framer-motion'
import type { AppProps } from 'next/app'
import 'styles/globals.css'
const MyApp = ({ Component, pageProps, router }: AppProps) => (
- <AnimatePresence exitBeforeEnter>
+ <AnimatePresence exitBeforeEnter onExitComplete={() => window.scrollTo(0, 0)}>
<Component key={router.asPath} {...pageProps} />
</AnimatePresence>
)
export default MyApp
onExitComplete={() => window.scrollTo(0, 0)}
を追加して、アンマウント完了後にページを先頭まで戻すようにします。
これでOKです! 🎉
あとがき
Framer Motion について、かなりシンプルな記述でアニメーションを実装することができ、とても楽しいなという印象を持ちました。
2Dアニメーションだけでなく 3Dアニメーション も扱えたりするようなので、もう少し色々触ってみようと思います!
参考
Author And Source
この問題について(Next.js + Framer Motion でページ遷移アニメーションを実装する), 我々は、より多くの情報をここで見つけました https://qiita.com/arrow2nd/items/b16385cf22c567fbbf33著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .