React+TypeScript環境にて画面遷移時のアニメーションを実装
2023/3/19 2023/3/21 システム
はじめに
この記事では、コーポレートサイト等の静的Webサイトなどではよく見かける画面遷移時のアニメーションを、React+TypeSctiptによるWebシステムに導入する際の方法を記載します。
Webシステムは機能面が優先されることが多いため利用されることは少ないかもしれませんが、画面遷移のアニメーションは手軽にリッチな印象を加えたい時などに活躍します。
今回画面遷移によるアニメーションはreact-rooter-domのv6 + framer-motionにて実装していきます。
パッケージのインストール
まずは既存のReactプロジェクトにnpmやyarnによりパッケージを追加します
yarn add react-router-dom framer-motion
https://www.framer.com/motion/
react-rooter-domとの組み合わせ方
react-rooter-domではRouterコンポーネント、Routesコンポーネント、Routeコンポーネントを定義してルーティングをしていきます。(Switchは現在非推奨となってます)
Routesにlocation={location}のpropsを与えたいのですが、Routerを使用しているApp.tsxでuseLocationを使ってしまうと、Routerの内部で使ってくださいと怒られてしまいます。
よって、App.tsx内にアニメーション用のWrapperコンポーネントを一つ作成していきます。
App.tsx
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import AnimateRoutes from 'AnimateRoutes';
const App: React.FC = () => {
return (
<Router basename="/">
<AnimateRoutes />
</Router>
);
};
export default App;
AnimateRoutesというコンポーネントを作成し、Router内で使用するようにしています。
続いて、AnimateRoutes内には今までApp.tsxで定義していた内容を記述し、本来やりたかったlocationの定義をRoutesに加えます
import React from 'react';
import { Route, Routes, useLocation } from 'react-router-dom';
import { AnimatePresence } from 'framer-motion';
const AnimateRoutes: React.FC = () => {
const location = useLocation();
return (
<AnimatePresence>
<Routes location={location} key={location.pathname}>
<Route path={"***"} element={<Top />} />
<Route path={"***"} element={<Pages />} />
</Routes>
</AnimatePresence>
);
};
export default AnimateRoutes;
AnimateRoutesはframer-motionのAnimatePresenceでwrapします。
elementに渡しているコンポーネントは一例で、各ページのコンポーネントを渡します。
そして、各コンポーネントごとに以下のようにアニメーションの設定を記載します。
この例では、各ページ共通のスタイルを当ててしまいたかったため、コンポーネントのレイアウトとして定義しているファイルに記述することにしました。
import React from 'react';
import { motion } from 'framer-motion';
import Sidebar from 'components/Sidebar';
const pageVariants = {
initial: {
opacity: 0,
},
in: {
opacity: 1,
},
out: {
opacity: 0,
},
};
const pageTransition = {
type: 'tween',
ease: 'easeInOut',
};
interface MainLayoutProps {
children: any;
}
export const MainLayout: React.FC<MainLayoutProps> = (
props: MainLayoutProps
) => {
const { children } = props;
return (
<>
<Sidebar />
<motion.div
initial="initial"
animate="in"
exit="out"
variants={pageVariants}
transition={pageTransition}
>
{children}
</motion.div>
</>
);
};
export default MainLayout;
import { motion } from ‘framer-motion’;にてmotionをインポートします。
そして、アニメーションを加えたいコンポーネントに対して<motion.div>で囲います。
上記では、サイドバーの部分は固定で表示させたかったためchildrenのみ囲っていますが、全画面にアニメーションを加えたい場合は全体を囲うことで適用することが可能です。
これだけで、画面遷移ごとにアニメーションを実装することが可能です。
※react-router-domによる遷移でなく、一般的な<a>タグ等を使用して画面遷移をしてしまうとうまくアニメーションが動かない場合があります。
Framer Motion のプロパティについて
上記例ではシンプルなフェードイン、フェードアウトによるアニメーションを加えています。
Framer Motionでは他にも以下のようなプロパティを設定することが可能です。
variants
:各状態でのプロパティの値を設定するオブジェクト。例えば、initial
状態と animate
状態で opacity
の値を変更したい場合は以下のように記述します。
const pageVariants = {
initial: { opacity: 0 },
in: { opacity: 1 },
out: { opacity: 0 }
};
transition
:アニメーションのトランジション(変化)を設定するオブジェクト。例えば、1 秒かけて opacity
を変化させたい場合は以下のように記述します。
const pageTransition = {
duration: 1,
opacity: { ease: 'easeOut', duration: 1 }
};
例えば、以下のように記述するとスライドインのアニメーションについても容易に実装することが可能です
const pageVariants = {
initial: {
x: '-100%',
opacity: 0,
},
in: {
x: 0,
opacity: 1,
},
out: {
x: '100%',
opacity: 0,
},
};
const pageTransition = {
type: 'tween',
ease: 'anticipate',
duration: 0.5,
};
variants
は、initial
、in
、out
の3つの状態を定義しています。initial
は、ページが画面の外側からスライドしてくる前の状態、in
は、ページが画面内にスライドしてきて表示される状態、out
は、ページが画面の外側にスライドしていく状態を表します。
x
プロパティは、ページの左右方向の位置を指定します。opacity
プロパティは、ページの不透明度を指定します。
transition
は、アニメーションの種類やイージング、アニメーションの時間などを定義します。この例では、type
を ‘tween’ に設定しているため、2つの状態間を滑らかに遷移する tween アニメーションが実行されます。ease
は、アニメーションのイージングを指定します。この例では、’anticipate’ というイージングを使用しています。duration
は、アニメーションの時間を秒単位で指定します。
最後に
コーポレートサイト等の静的Webサイトなどではよく見かける画面遷移時のアニメーションを、React+TypeSctiptによるWebシステムに導入する際の方法を記載しました。
最後まで閲覧いただきありがとうございました。