チャべログ

チャベス(@ChabesuB)のブログ。Notionのこと、プログラミングのこと、日常のこと。

A W E S O M E にローディングアニメーションを追加する

Notion AI
この記事を要約して

【Notion AI の要約】 ブログの記事で、ページ遷移時にローディングアニメーションを追加したことを紹介しています。ローディングアニメーションを実装するためのコードやCSSなども解説しています。記事の最後には今後の展望も述べられています。 【記事の文字数】830 文字

このブログでは元々 ISR を使っていましたが、Notion の画像のリンク切れの問題を解消するために SSR に変更しました。しかし SSR はページの表示が遅いため、ページ遷移時に画面が固まったように見えるかもしれません。そこで今回は、ページ遷移時にローディングアニメーションを追加することでブログを見ている方に「画面遷移中です」ということを伝えられるようにします。

実装結果は以下です。

SSR に変更した経緯については、以下のページを見てください。

ローディングアニメーションを実装する

ローディングアニメーションの実装については、以下のページを参考にさせていただきました。

まずは components フォルダの直下に spinner フォルダを作成します。

spinner フォルダに Loader.tsx を作成し、以下のコードを追加します。

components/spinner/Loader.tsx

import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import { Spinner } from "./Spinner";

const Loader = () => {
  const router = useRouter();
  const [loading, setLoading] = useState(false);
  useEffect(() => {
    const handleStart = (url: string) =>
      url !== router.asPath && setLoading(true);

    const handleComplete = () => setLoading(false);

    router.events.on("routeChangeStart", handleStart);
    router.events.on("routeChangeComplete", handleComplete);
    router.events.on("routeChangeError", handleComplete);
  }, [router.events, router.asPath]);

  return <>{loading && <Spinner />}</>;
};

export default Loader;
components/spinner/Loader.tsx

続いて、spinner フォルダに Spinner.tsx を作成し、以下のコードを追加します。

components/spinner/Spinner.tsx

import { FC } from "react";

export const Spinner: FC = () => {
  return (
    <>
      <div className="loadingWrap">
        <div className="loading" />
      </div>
      <style jsx>
        {`
          .loadingWrap {
            width: 100%;
            height: 100vh;
            background: rgba(0, 0, 0, 0.5);
            position: fixed;
            top: 0;
            left: 0;
            z-index: 10;
          }
          .loading {
            width: 5em;
            height: 5em;
            border-top: 1em solid rgba(255, 255, 255, 0.2);
            border-right: 1em solid rgba(255, 255, 255, 0.2);
            border-bottom: 1em solid rgba(255, 255, 255, 0.2);
            border-left: 1em solid rgba(255, 255, 255, 1);
            animation: loaderAnime 1s infinite linear;
            border-radius: 50%;
            position: fixed;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            margin: auto;
            z-index: 11;
          }
          @keyframes loaderAnime {
            0% {
              transform: rotate(0deg);
            }
            100% {
              transform: rotate(360deg);
            }
          }
          .loadingNone {
            animation: loadingAnime 1s forwards;
          }
          @keyframes loadingAnime {
            0% {
              opacity: 1;
            }
            99% {
              opacity: 0;
            }
            100% {
              opacity: 0;
              display: none;
            }
          }
        `}
      </style>
    </>
  );
};
components/spinner/Spinner.tsx

ちなみにローディングアニメーションの CSS については、以下のページを参考にさせていただきました。

最後に pages フォルダにある _app.tsx に以下を追加します。

pages/_app.tsx

import Loader from "../components/spinner/Loader";  //この行を追加
・
・
・
<GlobalStyle />
<Loader /> //この行を追加
<Component {...pageProps} />
pages/_app.tsx

これで実装が完了しました。

参考までに、このブログの今回の実装に関するコミットは以下です。

終わりに

今回は参考にさせていただいた記事のおかげで、簡単にローディングアニメーションを実装することができました。

現在は SSR を使っていますが、ISR + SWR 、もしくは 画像をキャッシュすることで、サイトを高速に表示しつつ画像のリンク切れ問題を解決することができそうなので、将来的にはチャレンジしたいと思っています。