26
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Reactでいい感じのページ遷移を実装してみよう!

Posted at

react-router-domとframer-motionを組み合わせていい感じのページ遷移を
実装できたので記事にします!

今回の目的

下のいい感じのページ遷移を実装!
Videotogif (3).gif

前提

React + typeScriptのプロジェクトを作成できる環境を作成できること

プロジェクト作成

create-react-app page-motion-sample-app --typescript

## 必要なパッケージのインストール

yarn add react-router-dom
yarn add @material-ui/core
yarn add framer-motion

ページを作成

src配下にpagesフォルダを作成して、今回使用するページを作成

src/pages/Left.tsx

import React from "react";

const Left = () => {
  return (
    <div>
      <div
        style={{
          width: "100%",
          height: 800,
          background: "chocolate",
          textAlign: "center"
        }}
      ></div>
    </div>
  );
};

export default Left;

src/pages/Under.tsx

import React from "react";

const Under = () => {
  return (
    <div>
      <div
        style={{
          width: "100%",
          height: 800,
          background: "antiquewhite",
          textAlign: "center"
        }}
      ></div>
    </div>
  );
};

export default Under;

src/pages/Right.tsx

import React from "react";

const Right = () => {
  return (
    <div>
      <div
        style={{
          width: "100%",
          height: 800,
          background: "aqua",
          textAlign: "center"
        }}
      ></div>
    </div>
  );
};

export default Right;

ルーティング作成

src/App.tsx のファイルを下記の様に変更

import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import None from "./pages/None";
import Left from "./pages/Left";
import Right from "./pages/Right";
import Under from "./pages/Under";

const App: React.FC = () => {
  return (
    <div className="App">
      <Router>
        <main role="main" className="pt-5">
          <Switch>
            <Route exact path="/" component={None} />
            <Route exact path="/left" component={Left} />
            <Route exact path="/right" component={Right} />
            <Route exact path="/under" component={Under} />
          </Switch>
        </main>
      </Router>
    </div>
  );
};

export default App;

移動用のナビバーを作成

src配下にcomponentsフォルダを作成して、ナビバーを作成

src/components/NavBar.tsx

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import BottomNavigation from "@material-ui/core/BottomNavigation";
import BottomNavigationAction from "@material-ui/core/BottomNavigationAction";
import ArrowForward from "@material-ui/icons/ArrowForward";
import ArrowBack from "@material-ui/icons/ArrowBack";
import ArrowDownward from "@material-ui/icons/ArrowDownward";
import { Grid } from "@material-ui/core";
import { withRouter } from "react-router";

const useStyles = makeStyles({
  root: {
    width: 500
  }
});

const NavBar = (props: any) => {
  const classes = useStyles();
  const [value, setValue] = React.useState(0);

  return (
    <Grid container alignItems="center" justify="center">
      <BottomNavigation
        value={value}
        showLabels
        className={classes.root}
        style={{
          width: "100%"
        }}
      >
        <BottomNavigationAction
          label="左"
          icon={<ArrowBack />}
          onClick={() => {
            props.history.push("/left");
          }}
        />
        <BottomNavigationAction
          label="下"
          icon={<ArrowDownward />}
          onClick={() => {
            props.history.push("/under");
          }}
        />
        <BottomNavigationAction
          label="右"
          icon={<ArrowForward />}
          onClick={() => {
            props.history.push("/right");
          }}
        />
      </BottomNavigation>
    </Grid>
  );
};

export default withRouter(NavBar);

NabBarを各Pageに組み込む

こんな感じで上で作成したNabBarを全ページに組み込んでいきます

import React from "react";
{/*  ここから */}
import NavBar from "../components/NavBar";
{/*  ここからここまで追加 */}

const Left = () => {
  return (
    <div>
      {/*  ここから */}
      <NavBar />
      {/*  ここからここまで追加 */}
      <div
        style={{
          width: "100%",
          height: 800,
          background: "chocolate",
          textAlign: "center"
        }}
      ></div>
    </div>
  );
};

export default Left;

ここまで組み込むと最低限動く形になりました!
Videotogif.gif

次は動きを追加します!

ページ遷移時に動きをつけるファイルを作成

src/components/motion配下に、ページ遷移時に動きをつけるファイルを作成

src/components/motion/LeftMotion.tsx

import React from "react";
import { motion } from "framer-motion";

const LeftMotion: React.FC<{
  children: JSX.Element;
}> = ({ children }) => {
  return (
    <motion.div
      animate={{
        x: 0,
        opacity: 1
      }}
      initial={{
        x: -500,
        opacity: 0
      }}
      exit={{
        x: 0,
        opacity: 0
      }}
      transition={{
        duration: 0.3
      }}
    >
      {children}
    </motion.div>
  );
};

export default LeftMotion;

src/components/motion/RightMotion.tsx

import React from "react";
import { motion } from "framer-motion";

const RightMotion: React.FC<{
  children: JSX.Element;
}> = ({ children }) => {
  return (
    <motion.div
      animate={{
        x: 0,
        opacity: 1
      }}
      initial={{
        x: 500,
        opacity: 0
      }}
      exit={{
        x: 0,
        opacity: 0
      }}
      transition={{
        duration: 0.3
      }}
    >
      {children}
    </motion.div>
  );
};

export default RightMotion;

src/components/motion/UnderMotion.tsx

import React from "react";
import { motion } from "framer-motion";

const UnderMotion: React.FC<{
  children: JSX.Element;
}> = ({ children }) => {
  return (
    <motion.div
      animate={{
        y: 0,
        opacity: 1
      }}
      initial={{
        y: 500,
        opacity: 0
      }}
      exit={{
        y: 0,
        opacity: 0
      }}
      transition={{
        duration: 0.3
      }}
    >
      {children}
    </motion.div>
  );
};

export default UnderMotion;

ページ遷移時の動きを各Pageに組み込む

こんな感じで上で作成したファイルを全ページに組み込んでいきます

import React from "react";
{/* ここから */}
import UnderMotion from "../components/motion/UnderMotion";
{/* ここまで変更 */}
import NavBar from "../components/NavBar";

const Under = () => {
  return (
    <div>
      <NavBar />
      {/* ここから */}
      <UnderMotion>
        <div
          style={{
            width: "100%",
            height: 800,
            background: "antiquewhite",
            textAlign: "center"
          }}
        ></div>
      </UnderMotion>
      {/* ここまで変更 */}
    </div>
  );
};

export default Under;

上記の追加が終わればいい感じのページ遷移が確認できます!

Videotogif (3).gif

Gifがいまいちなので実際の動きを正確に確認したい方は、GitHubからコードを落として確認してください!
https://github.com/aokisinn/page-motion-sample-app

あと、Macでいい感じのGif作成できるアプリ知っている方いたらコメントで教えてください!!!

26
40
2

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
26
40

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?