react-intersection-observerとは?

今回は小ネタです。
Intersection Observer APIをReactで簡単に扱うためのライブラリであるreact-intersection-observerを紹介します。
react-intersection-observer

このライブラリは要素がViewに入ったことを検出することができます。内部ではIntersection Observer APIが実行されています。
MDN | Intersection Observer API

使用用途としては、画像の遅延読み込みやアニメーションのトリガーとしたりすることが挙げられています。
Intersection Observer APIを使うには要素の情報を取得したりといった処理を書く必要があるのですが、このライブラリを使うと簡単に行うことができます。
Intersection Observer APIが行う処理については以下のページが分かりやすいので参照ください。
icsMedia | JSでのスクロール連動エフェクトにはIntersection Observerが便利

アニメーションを実装する

今回はこのライブラリを用いて、要素がViewに入ったらフワッと出現させるようなアニメーションを書く方法を紹介しようと思います。
Aboutページのアニメーションは今回紹介する方法で実装されています。
https://ryusou.dev/about

使用ライブラリ

react-intersection-observer v8.26.2
@emotion/core v10.0.28
今回発火させるアニメーション自体はReactのCSSinJSライブラリであるemotionを使用します。emotionやstyled-componentなどのCSSinJSを使用すると、アニメーションの分岐処理などがスマートに書けます。

また、react-intersection-observerにはHooksやRenderPropsなどの様々な書き方が用意されていますが、今回はHooksを使った書き方を紹介します。

使い方

では、実際に使い方を紹介します。
ライブラリをインストールします。TypeScriptで作成されているのでtypesはインストールする必要はありません。

yarn add react-intersection-observer


react-intersection-observerも他のReactライブラリと同様にコンポーネントに使用していきましょう。
以下はページのサブタイトル(h2要素)に適用した例です。

import React from 'react';
import { useInView } from 'react-intersection-observer';
import { colors, sizes } from '../../../theme';
import { BottomIn } from '../../../keyframes';

export const SubTitle: React.FC = ({ children }) => {
  const [ref, inView] = useInView({
    rootMargin: '-50px 0px',
  });
  return (
    <h2
      ref={ref}
      css={{
        margin: `${sizes[16]} auto 0`,
        textAlign: 'center',
        color: colors.blue,
        opacity: inView ? 1 : 0,
        animation: inView ? `${BottomIn} 0.5s ease-out` : 0,
      }}
    >
      {children}
    </h2>
  );
};


以下のようにHooksを使って簡単に書くことができます。refで要素を指定して、inViewを使って要素がViewに入ったかどうかを判定します。

 const [ref, inView] = useInView({
    rootMargin: '-50px 0px',
  });


与えられるOptionは以下のとおりです。
Option
今回はrootMarginを設定しました。上記のように設定することによって、要素が50pxより上に入った段階でinViewを取得できます。

CSSinJSを使えば上記のようにしてアニメーションを発火できます。今回は初期状態のOpacityを0にして、出現するようなアニメーションを実装してみました。

export const BottomIn = keyframes({
  '0%': {
    opacity: 0,
    transform: `translateY(${sizes[4]})`,
  },
  '50%': {
    opacity: 0.5,
    transform: `translateY(${sizes[2]})`,
  },
  '100%': {
    opacity: 1,
    transform: `translateY(0)`,
  },
});


まとめ

今回は簡単にReactでIntersection Observer APIを使うreact-intersection-observerを紹介しました。
とても便利なので、ぜひ使ってみてください。