見出し画像

【Lottie x Next.js】よく動くアニメーションの実装

はじめに

Next.jsにおけるLottieを利用したアニメーションの実装方法を紹介します。


Lottieとは

Lottieとはベクトルアニメーションのファイル形式のことであり、
JSONファイルが使われるため、非常に軽いサイズでアニメーションを実装することができ、SVGで出力されるため、サイズを拡大しても荒れたりせずに綺麗に表示されます。

Lottieファイルの準備

LottieFilesLordiconからLottieファイルをGETしましょう。
どちらのサイトもフリーの素材が多く色の変更やアニメーションの微調整可

実装

ライブラリのインストール

こちらのコマンドでライブラリをインストール

npm install lottie-web

実装イメージ

下記の流れで実装します。

  1. useStateを利用してLottieインスタンスを定義する

  2. useRefを利用してLottieを表示する要素を定義する

  3. useEffectを利用してコンポーネントのmount時にLottieをインポートする

  4. 3のタイミングでインポートしたLottieを1のstateに格納する

  5. 4のLottieをstateに格納したタイミングでLottieを読み込み2の要素に表示する

import { useEffect, useRef, useState } from 'react'
import { GlobeLoopParams, GlobeClickParams, GlobeHoverParams } from '../../public/lottieParams'

const LottiSection = () => {
  // lottieインスタンスを定義する  
  const [lottie, setLottie] = useState<any>(null)
  // lottieを表示する要素を定義する  
    const globeLoop = useRef(null)
  const globeClick = useRef(null)
  const globeHover = useRef(null)
  // 名前とイベントに応じてlottieを操作する  
  const lottieHandler = (name: string, event: string) => {
    switch (event) {
      case 'click':
        lottie.play(name)
        setTimeout(() => {
          lottie.pause(name)
        }, 500)
        break      
      case'mouseOver':
        lottie.play(name)
        break      
      case 'mouseOut':
        lottie.pause(name)
        break    
    }
  }
  // マウント時にlottieインスタンスを作成し、stateに格納する  
  useEffect(() => {
    import('lottie-web').then((Lottie) => setLottie(Lottie.default))
  }, [])
  // lottieインスタンスの作成時にパラメータを引数に入れてアニメーションを読み込む  
  useEffect(() => {
    if (lottie) {
      GlobeLoopParams.container = globeLoop.current      
      const animationLoop = lottie.loadAnimation(GlobeLoopParams)
      GlobeClickParams.container = globeClick.current      
      const animationClick = lottie.loadAnimation(GlobeClickParams)
      GlobeHoverParams.container = globeHover.current      
      const animationHover = lottie.loadAnimation(GlobeHoverParams)
      return () => {
        animationLoop.destroy()
        animationClick.destroy()
        animationHover.destroy()
      }
    }
  }, [lottie])
    return (
    <div>
      <div>
        <p>Loop</p>
        <div
          className={styles.lottie} ref={globeLoop}
        />
      </div>
      <div>
        <p>Click</p>
        <div
          className={styles.lottie} ref={globeClick}
          onClick={() => lottieHandler('globeClick', 'click')}
        />
      </div>
      <div>
        <p>Hover</p>
        <div
          className={styles.lottie} ref={globeHover}
          onMouseOver={() => lottieHandler('globeHover', 'mouseOver')}
          onMouseOut={() => lottieHandler('globeHover', 'mouseOut')}
        />
      </div>
    </div>
  )
}
export default LottiSection

解説

export const GlobeLoopParams = {
  container: null,
  name: 'globeLoop',
  renderer: 'svg',
  loop: true,
  autoplay: true,
  path: '/globe.json',
  style: {
    width: '200px',
    height: '200px'
  },
}

アニメーションのパラメータは別ファイルで定義してます。

containerというプロパティはuseRefで参照する要素の値が入るためnullとしてます。

const lottieHandler = (name: string, event: string) => {

イベントごとのlottieの操作を行なってる関数です。
click:クリックした際のアニメーション
mouseOver:
マウスカーソルを合わせた際のアニメーション
mouseOut:
マウスカーソルを離した際のアニメーション

今回はmouseOverでアニメーションを動かして、mouseOutでアニメーションを止めてます。

最後に

簡単にアニメーションを表示できて大変便利だと感じました。
アイコンを動かしたりとちょっとしたアクセントになりそうです。
今回はフリー素材を利用しましたが、自作の動画をJSON形式に描き出せればよりハイクオリティなWEBページが作れそうです。


参考

https://github.com/airbnb/lottie-web

https://stackoverflow.com/questions/69282996/lottie-files-reducing-performance-on-nextjs-app

https://github.com/LottieFiles/lottie-player

https://docs.lottiefiles.com/lottie-player/components/lottie-player

この記事が気に入ったらサポートをしてみませんか?