Lottieアニメーションをスクロール量に応じて制御する
GSAPのScrollTriggerでLottieアニメをスクロール量に応じて再生します。
DEMO
lottieを描画する部分をposition:fixdedで固定しています。
クリックするとtopに戻ります。
Lottieとは
Lottie(ロッティー)は、Airbnbが開発したライブラリで、ウェブやモバイルアプリケーションでベクトルアニメーションを再生するためのツールです。
Lottieのメリット
- ベクトルアニメーションのサポート: Lottieはベクトル形式のアニメーションをサポートしており、異なる画面サイズや解像度に対しても高品質なアニメーションを提供します。
- プラットフォームの対応: LottieはWeb(JavaScript)、iOS(Swift/Objective-C)、Android(Java/Kotlin)の各プラットフォームで利用可能です。
- After Effectsとの統合: LottieはAdobe After Effectsと統合でき、デザイナーはAfter Effectsでアニメーションを制作し、そのデータをLottieが解釈できるJSON形式にエクスポートすることができます。
- 軽量で高性能: LottieはコンパクトなJSON形式を使用しているため、アニメーションデータが比較的小さく、ネットワーク通信やアプリケーションのパフォーマンスにおいても効率的です。
- 多彩なアニメーション効果: イージングやトリガーアクション、ループ、逆再生など、さまざまなアニメーション効果をサポートしています。
Lottieのデメリット
- 単色のsvgでないと無理 : グラデーションでの塗りつぶしは不向きな様です
- アクセシビリティへの対応が必要:altタグやスクリーンリーダーへの対応が別途必要な様です
いちばん簡単な再生方法
CDNを読み込みlottie-player
タグを貼ることで簡単に再生できます。
以下のリンクでパラメータをいじりつつコードを作成できます。
Lottieファイルの作成
LottieファイルはAfter Effects, FIGMA, Lottie Creatorなどで作成することができます。
今回はプラットフォームに公開されているファイルを使用するため、作成方法については割愛します。
以下のリンクが参考になるかと思います。
ScrollTriggerでLottieを制御する
本記事の肝です。まずは完成コードを御覧ください。
viteを使用しています。
JSONファイルはpublicフォルダ直下から呼び出しています。
完成コード
ディレクトリ構成
\lottie-vite\
│ .gitignore
│ index.html
│ main.js
│ package-lock.json
│ package.json
│ style.css
├─node_modules
└─public
sample_01.json
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>ScrollTriggerSample</title>
<body class="home">
<h1>ScrollTriggerSample</h1>
<a href="#">
<div id="animationWindow"></div>
</a>
<script type="module" src="/main.js"></script>
</body>
</html>
style.css
body.home {
height: 300vh;
width: 100%;
margin: 0;
padding: 0;
}
h1 {
font-size: clamp(16px,2vw,32px);
position: fixed;
top: 20%;
left: 20%;
}
#animationWindow {
max-width: 60%;
aspect-ratio: 800 / 400;
height: auto;
position: fixed;
bottom: 20%;
left: 20%;
border: solid 1px black;
}
main.js
import './style.css'
import gsap from "gsap";
import lottie from 'lottie-web';
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
const ScrollLottie = (obj) => {
let anim = lottie.loadAnimation({
container: document.querySelector(obj.target),
renderer: "svg",
loop: false,
autoplay: false,
path: obj.path,
});
let timeObj = { currentFrame: 0 };
let endString =
obj.speed === "slow"
? "+=2000"
: obj.speed === "medium"
? "+=1000"
: obj.speed === undefined
? "+=1250"
: "+=500";
ScrollTrigger.create({
trigger: obj.target,
scrub: true,
markers: true,
// pin: true,
start: "top top",
end: endString,
onUpdate: (self) => {
if (obj.duration) {
gsap.to(timeObj, {
duration: obj.duration,
currentFrame: Math.floor(
self.progress * (anim.totalFrames - 1),
),
onUpdate: () => {
anim.goToAndStop(timeObj.currentFrame, true);
},
ease: "expo",
});
} else {
anim.goToAndStop(
self.progress * (anim.totalFrames - 1),
true,
);
}
},
});
};
ScrollLottie({
target: "#animationWindow",
path: "./sample_01.json",
duration: 1,
speed: "slow",
});
依存関係のインストール
npm install lottie-web
npm install gsap
import lottie from 'lottie-web';
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
lottie-web, gsap, ScrollTriggerをインストールします。
CDNでも可能ですが割愛させていただきます。
Lottieアニメーションのロード
let anim = lottie.loadAnimation({
container: document.querySelector(obj.target),
renderer: 'svg',
loop: false,
autoplay: false,
path: obj.path
});
lottie.loadAnimationメソッドを使用して、指定されたobj.target内にLottieアニメーションをロードします。rendererはSVGを使用し、loopはアニメーションのループを無効に、autoplayは自動再生を無効に、pathはアニメーションのJSONファイルのパスを指定します。
ScrollTriggerの設定
ScrollTrigger.create({
trigger: obj.target,
scrub: true,
markers: true,
start: "top top",
end: endString,
onUpdate: self => {
// ...
}
});
ScrollTriggerを作成して、スクロールに応じてアニメーションを制御するための設定を行います。scrubはスクロールに応じてアニメーションを滑らかに制御し、startとendはアニメーションのトリガーの範囲を指定します。onUpdateコールバックでは、スクロールの進捗に応じてアニメーションの進行を更新します。
アニメーションの進捗に応じた処理
onUpdate: self => {
if(obj.duration) {
gsap.to(timeObj, {
duration: obj.duration,
currentFrame:(Math.floor(self.progress * (anim.totalFrames - 1))),
onUpdate: () => {
anim.goToAndStop(timeObj.currentFrame, true)
},
ease: 'expo'
})
} else {
anim.goToAndStop(self.progress * (anim.totalFrames - 1), true)
}
}
onUpdateコールバック内では、スクロールの進捗に応じてアニメーションの進行を制御します。もしobj.durationが指定されていれば、GSAPのtoメソッドを使用して指定された時間でアニメーションを進めます。それ以外の場合は、スクロールの進捗に基づいてアニメーションを進行させます。
プロパティの設定
ScrollLottie({
target: "#animationWindow",
path: "./sample_01.json",
duration: 1,
speed: "slow",
});
プロパティを設定してScrollLottieを呼び出します。
参考資料
GSAP公式にScrollTriggerでの制御について掲載されているのですが、そのinspire元を今回は参考にさせていただきました。
Appendix
今回はGSAPで制御しましたが、lottieをインタラクティブに制御する手段を公式で用意してくれています。
Discussion