【Lottie x Next.js】よく動くアニメーションの実装
はじめに
Next.jsにおけるLottieを利用したアニメーションの実装方法を紹介します。
Lottieとは
Lottieとはベクトルアニメーションのファイル形式のことであり、
JSONファイルが使われるため、非常に軽いサイズでアニメーションを実装することができ、SVGで出力されるため、サイズを拡大しても荒れたりせずに綺麗に表示されます。
Lottieファイルの準備
LottieFilesやLordiconからLottieファイルをGETしましょう。
どちらのサイトもフリーの素材が多く色の変更やアニメーションの微調整可
実装
ライブラリのインストール
こちらのコマンドでライブラリをインストール
npm install lottie-web
実装イメージ
下記の流れで実装します。
useStateを利用してLottieインスタンスを定義する
useRefを利用してLottieを表示する要素を定義する
useEffectを利用してコンポーネントのmount時にLottieをインポートする
3のタイミングでインポートしたLottieを1のstateに格納する
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