【Gatsby製ブログ】framer-motionでスクロールしたらフワッと表示させる

PR

Reactでアニメーションをつけるときにオススメのライブラリーがframer-motionです。

もちろんReactベースのGatsbyでも使うことができます。

私のGatsbyブログでもframer-motionでアニメーションをつけています。

framer-motionは自由度が高く、色々できる代わりに使い方が結構複雑ですので、丁寧に説明していきたいと思います。

今回はframer-motionの応用、スクロールアニメーションについて説明していきます!

LINEスタンプもぜひご覧ください!

目次

framer-motionでスクロールアニメーション…の前に

スルロールアニメションを作る前に、少しHooksの説明をしておきます。

framer-motionの基本とReactのHooksの話が出てきますので、こちらも合わせて読んでいただければ、と思います。

クマ

今回はその他にuseAnimationuseInViewというHooksを使います。

useAnimation

useAnimationはアニメーションの制御をするHooksです。

こちらで説明した「ラジオボタンを選んだときにその色に変わる」というアニメーションもuseAnimationを使って書くことができます。

import { motion, useAnimation } from "framer-motion" //useAnimationをframer-motionからインポートする
…

- const [color, setColor] = useState("red"); //このuseStateは必要なし
+ const control = useAnimation(); //代わりにuseAnimationでアニメーションのコントロールをする

- const colorChange = (e) => {setColor(e.target.value)} ;
+ const colorChange = (e) => {control.start(e.target.value)} ;
//さっき定義したuseAnimationを「.start("アニメーション先")」でアニメーションスタートさせる。
//"アニメーション先"はvariantsでの状態名を指定もいいし、直接状態を定義してもOK。

const changeColorVariants = { //状態を3つ(red、blue、green)Variantsで準備しておく。
  red: {
    color: "white",
    backgroundColor: "#ff0000",
    transition: {
      duration: 2,
    }
  },
  blue: {
    color: "white",
    backgroundColor: "#0080ff",
    transition: {
      duration: 2,
    }
  },
  green: {
    color: "white",
    backgroundColor: "#00fa9a",
    transition: {
      duration: 2,
    }
  }
}

return (
  …
  <motion.div
    variants = {changeColorVariants}
    initial = "red"
    - animate = {color} 
    + animate = {control} //animateには定義したuseAnimationのコントロールを指定
    style={{fontSize:"3rem", width: 600, height: 200, textAlign: "center", lineHeight: "200px" }}
  >
    Variantsのテストだよ
  </motion.div>
  <input type = "radio" name ="colorselect" value = "red" onChange = {colorChange} }/><label>赤</label>
  <input type = "radio" name ="colorselect" value = "blue" onChange = {colorChange} }/><label>青</label>
  <input type = "radio" name ="colorselect" value = "green" onChange = {colorChange} /><label>緑</label>
  …
)
クマ

useStateをかませる必要がなく「.start(“アニメーション先”)」でシンプルにアニメーション発火ができるのでわかりやすいです。
今回はこれをuseEffectに入れておきます。

useInView

useInViewは要素が画面内に入ったかどうか判定するHooksです。

まずは、react-intersection-observerをインストールします。

$ yarn add react-intersection-observer

そして、react-intersection-observerからuseInViewをインポートしておいて、次のように使います。

import { useInView } from 'react-intersection-observer' //useInViewをreact-intersection-observerからインポート
…

const [ref, inView] = useInView();

…
<div ref={ref}>この要素が入ったらinViewがtrueになるよ。</div>
クマ

これ単体でアレコレ言っても面白くないので、実際にスクロールアニメーションを作りながら説明します。

framer-motionでスクロールアニメーションを作る

それでは、framer-motionを使ってスクロールアニメーションを作っていきましょう!

クマ

早速ですが、コードを見てみましょう。

import React, { useEffect } from "react";
import Layout from "../components/layout";
import { motion, useAnimation } from "framer-motion";
import { useInView } from "react-intersection-observer";

const ScrollAnimationTest = ({ data, location }) => {
  const control = useAnimation(); //useAnimationを使ってコントローラーを作っておく。
  const [ref, isInView] = useInView({triggerOnce: true}); 
  //↑useInView。refで参照している要素が画面内に入ったらisInViewがtrueになる

  const scrollVariants = {
    visible: {
      y: 0,
      opacity: 1,
      transition: {
      //duration(アニメーションの長さ)とdelay(アニメーションを遅らせる)をイイカンジに設定する。
      //そうしないとスクロールアニメーションっぽくない。
        duration: 1,
        delay: 0.8,
        type: "spring",
      },
    },
    hidden: {
      y: 30,
      opacity: 0,
    },
  }

  useEffect( //useEffectを使って、要素が画面内に入ったらcontrolをvisibleにする
    ()=>{
      if(isInView){
        control.start("visible");
      }
    },
    [isInView]
  );

  return (
    <Layout location={location} title="Scroll Animation Test" >
      <div style={{fontSize: "5rem", height: "150vh"}}>
        あれは…なんだ!?
      </div>

      <motion.div
        style={{fontSize: "8rem", height: "50vh"}}
        ref = {ref} //refで、useInViewでこの要素を参照するようにする。
        variants = {scrollVariants}
        initial = "hidden"
        animate = {control} //animateはcontrolを指定。これでcontrolの状態にアニメーションしていく
      >
        クマだ!!クマが出たぞ!
      </motion.div>
    </Layout>
  )
}

export default ScrollAnimationTest
スクロールアニメーション1

これだけで、簡単にスクロールアニメーションを実装することができました!

クマ

とはいえ、useAnimation、useInViewとuseEffectがからみ合ってるので、Hooksに慣れてないと最初はわかりにくいかもしれません…。

useInViewは

const [ref, isInView] = useInView({triggerOnce: true}); 

とすることで、要素が画面に入ったかどうか一度だけ判定します。その後、画面から外れてもisInViewはtrueになったままですのでアニメーションは一度だけ発火する、ということになります。

ですが、今回は、

const [ref, isInView] = useInView(); 

としていても、アニメーションとしては一度だけしか発火しません。

これだと、確かに要素が画面内に入ればisInViewはtrue、外れればfalseになります。

ですが、falseになったときのcontrolの値変更の処理を書いていないので、一度control.start(“visible”)になってしまえば”hidden”に戻らないからです。

framer-motionでスクロールアニメーション(ちょっと応用)

ということで、先ほどのコードを少しいじって、要素が画面外に外れてもう一度入ったら、再びアニメーションが発火するようにしてみましょう。

クマ

さっきのメモ部分がわかっていれば、すぐにやり方はイメージできるはずです!変更箇所だけ載せておきます。

…
-  const [ref, isInView] = useInView({triggerOnce: true}); 
+  const [ref, isInView] = useInView(); //triggerOnceを外して、何度でも判定をするようにする。 
…
  useEffect(
    ()=>{
      if(isInView){
        control.start("visible");
      }
+      if(!isInView){ //画面外に外れた際のcontrolを"hidden"にする処理を追加
+        control.start("hidden");
+      }
    },
    [isInView]
  );
…
スクロールアニメーション2

何度もアニメーションを発火させたいときは、このようにisInViewがfalseになったときの処理を追加しましょう。

まとめ

スクロールアニメーションを実装するだけで、かなりサイトがリッチに見えます。

手軽な上に実用的ですので、アニメーションの手始めにいかがでしょうか?

ちょっと一息…

最近本格的にCSSの勉強を始めました。

WordPressでもGatsbyJSでも必要な基本的な知識「CSS」…これが奥深い。

クマ

もちろんCSSに関する基本的な知識はあるのですが、引き出しは多くしておきたいものです。

ワンランク上のホームページ、ブログ作成を目指して、特に「これはよかった」というオススメのCSS学習教材の紹介をしていきます。

動画編

Webデザインのオンラインスクールなどは沢山ありますが、数万円〜数十万円するので、なかなかハードルが高いですよね。

そこでオススメなのはUdemy

このブログでもちょくちょく紹介させてもらっていますが、一つの講座買い切り、というのがありがたいです。

しかも、種類もかなり豊富!GatsbyJSの講座まである、というのは他ではなかなかないです。

そのなかでもオススメのCSSに関する講座を紹介しておきます。

クマ

CSSの講座とかは沢山あるので、「これよさそう!」と思ったものを探すのも楽しいかもしれません。

書籍編

CSSを実践的に書いていくなら、書籍も便利です。

本を片手にコーディング、というのは効率もいいですよね。

こちらもオススメの本を紹介しておきます。

クマ

CSSの基本ができている人が「次のステップに行きたいなぁ…」というときにオススメです。

あなたへオススメ!
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次