#はじめに
フロントエンドでReactやNextJSを使用しているときにスクロールアニメーションをコンポーネント化して簡単に使用する方法を見つけたので、共有します。
#スクロールアニメーションを実装する
アプリケーションやWebサイトを作成する時にアニメーションがあったりすると途端に本格的に見えたりしますが、CSSで実装するのは中々面倒だったりします。
今回紹介するのは「scrollreveal」というライブラリとReactを使用して再利用性の高いアニメーションコンポーネントを作成していきたいと思います。
##ScrollReveal
ScrollRevealはJavascriptでスクロールアニメーションが実装できるようになるライブラリで、よくWebサイトで見る「スクロールしたらふわっと出てくる」アニメーション効果を与えてくれます。
公式ドキュメント
使用するには、script
タグで読み込むかnpm(yarn)でライブラリをインストールします。
//scriptで読み込み
<script src="https://unpkg.com/scrollreveal"></script>
//npm(yarn)でインストール
npm i -S (yarn add) scrollreveal
typescript
を使用している方は、別途型定義ファイルも必要なので、インストールします。
npm i -S -D(yarn add -D) @types/scrollreveal
アニメーション効果をつけるにはScrollReveal().reveal()
メソッドで対象のclass
等を指定すれば、簡単にアニメーション効果をつけることができます。
//第二引数で効果時間の設定等が可能。詳しくは公式ドキュメントを参照して下さい
ScrollReveal().reveal('.container', {
duration: 500,
reset: true
})
##Reactでコンポーネント化
次にReactで要素をラップすればアニメーション効果を付与できるコンポーネントを作成します。
import { FC, useRef, useEffect } from "react";
import scrollReveal from "scrollreveal";
interface ScrollRevealContainerProps {
move?: string;
}
const ScrollRevealContainer: FC<ScrollRevealContainerProps> = ({
children,
move
}) => {
const sectionRef = useRef<HTMLElement>(null);
useEffect(() => {
if (sectionRef.current)
scrollReveal().reveal(sectionRef.current, {
reset: true,
delay: 400,
opacity: 0,
origin:
move === "left"
? "left"
: move === "right"
? "right"
: move === "top"
? "top"
: "bottom",
distance: "40px"
});
}, [sectionRef]);
return <section ref={sectionRef}>{children}</section>;
};
export default ScrollRevealContainer;
このコンポーネントではReactのuseRef
,useEffect
を用いてアニメーション発動のタイミングを設定しています。
まずuseRef
でこのコンポーネントまでスクロールした時にDOMを参照し、useEffect
でDOMが参照される度にscrollreveal
のメソッドを実行するようにします。
また任意でprops
を渡せるようにしており、left
,right
,top
,bottom
の中から渡した値の方向からコンポーネントがスクロールして表れるようにしています(何もprops
を渡さなければ下部から表れます)。
あとはアニメーションを実装したい要素をこのコンポーネントで囲むだけです。
import ScrollRevealContainer from "./ScrollRevealContainer";
export default function App() {
return (
<>
<div style={{ marginBottom: "400px" }}></div>
<ScrollRevealContainer move="right">
<h1>右から登場</h1>
<h2>Edit to see some magic happen!</h2>
</ScrollRevealContainer>
<ScrollRevealContainer move="left">
<h1>左から登場</h1>
<h2>Edit to see some magic happen!</h2>
</ScrollRevealContainer>
<ScrollRevealContainer move="top">
<h1>上から登場</h1>
<h2>Edit to see some magic happen!</h2>
</ScrollRevealContainer>
{/* ↓props「move」に何も指定しなければ「origin」は「bottom」になる */}
<ScrollRevealContainer>
<h1>下から登場</h1>
<h2>Edit to see some magic happen!</h2>
</ScrollRevealContainer>
</>
);
}
このように要素をScrollRevealContainer
コンポーネントで囲むだけで簡単に実装できました!
実際にはこのように動作するので確認してみて下さい↓
Code Sandbox
##NextJSで使用する際の注意点
Reactでは上記の方法で動作するのですが、同じ方法をNextJSで実装するとdocument is not defind
というエラーが表示されます。
これはレンダリング方法の違いによって起こるものであり、NextJSは開発モード時デフォルトでSSR(Server Side Rendering)でレンダリングされるのですが、サーバーサイドに存在しないdocument
を参照しているためにこのようなエラーが発生します。
解決方法としてはnext/dynamic
を使用してコンポーネントを動的インポートし、さらにオプションssr:false
を指定して対象のコンポーネントをSSRさせないようにすればOKです。
//動的インポートを使用し、オプションでSSRさせないよう設定
const ScrollRevealContainer = dynamic(
import('./ScrollRevealContainer'),
{ssr: false,}
);
こうすればエラーが解消されます!
参考:Next.jsでwindow is not definedを解決する(依存ライブラリ対応)
#まとめ
React(NextJS)を使用して再利用性の高いアニメーションコンポーネントで作成できました。
今後も新しい情報が入り次第随時更新していきます。