
React(JSX・TSX)のコンポーネントでGSAPを使ってみる #2:スクロール固定表示のアニメーション
前回に引き続きReactのコンポーネントでGSAPをつかってアニメーションを実装する例を見ていきます。今回はScrollTriggerのプラグインを使ってスクロールに連動させる処理を作成するパターンです。新たに注意しておくポイントがありますので、その辺りも含めてチェックしていきたいと思います。
(過去の参考記事もどうぞ)
React(JSX・TSX)のコンポーネントでGSAPを使ってみる #1:要素のアニメーション
GSAPとvivusを使ったSVGのドローアニメーション
GSAPでScrollTriggerプラグインを使ったスクロール固定表示アニメーションの応用
GSAPでScrollTriggerプラグインを使ってスクロールに対応したアニメーションを実装してみる#3:スクロールで固定表示
GSAPでScrollTriggerプラグインを使ってスクロールに対応したアニメーションを実装してみる#2:スクロール量に連動
GSAPでScrollTriggerプラグインを使ってスクロールに対応したアニメーションを実装してみる#1:基本編
JavaScriptのアニメーションライブラリ「GSAP」を使ってみる
今回はScrollTriggerのpinオプションをつかってコンテンツを固定表示させながらスクロールにあわせて切り替えていく処理をサンプルとして見ていきます。過去記事「GSAPでScrollTriggerプラグインを使ってスクロールに対応したアニメーションを実装してみる#3:スクロールで固定表示」でも同様の動きを紹介していますが、今回は少し別のアプローチになります。
それではコンポーネントを見ていきます。GSAPなど必要なライブラリを読み込み、それぞれHTMLに要素を展開していきます。ReactのコンポーネントではDOMをuseRefを使って参照します。またスクロールに合わせて切り替えるコンテンツである背景画像と前面テキストはそれぞれuseStateによってコンポーネント内のステートとして管理します。この値をスクロール量にあわせて更新することで表示を切り替えるようにする仕組みです。アニメーション部分の処理ですが、まずpinのオプションを有効化することでコンテンツ全体が固定表示となります。そして固定表示のコンテンツがスクロールされている間に切り替わるのが認識できるようscrollTriggerのendオプションで固定させる高さをビューポートの5倍になるようにするのもポイントです。また、onUpdateのオプションでスクロール進捗にあわせてステートを切り替える処理をコールバックで用意します。このコールバック関数の引数から「progress」のキーを参照することで全体のスクロール量に対して現在のスクロール量の進捗割合を取得することができます。今回は固定スクロールエリア内で3種類で切り替わるようにするため、進捗全体を3分割にしたところで処理を分岐させます。
今回はReactでGSAPをつかったスクロールに連動させたアニメーションを実装するパターンについて見ていきました。useEffectの仕様など、注意したいポイントがありますので覚えておきたいですね。
import { useRef, useState, useEffect } from "react";
import gsap from "gsap";
import ScrollTrigger from "gsap/ScrollTrigger";
import "./styles.css";
export default function App() {
const didEffect = useRef(false);
const refTrigger = useRef<HTMLDivElement | null>(null);
const refElement = useRef<HTMLDivElement | null>(null);
const refTitle = useRef<HTMLHeadingElement | null>(null);
const [title, setTitle] = useState("コンテンツタイトル1");
const [image, setImage] = useState("image_01.jpg");
const fixedScroll = () => {
gsap.to(refElement.current, {
scrollTrigger: {
trigger: refTrigger.current,
start: "top top",
end: "bottom+=400% bottom",
scrub: true,
pin: true,
anticipatePin: 1,
invalidateOnRefresh: true,
onUpdate: (self) => {
if (
0 <= Math.floor(self.progress * 100) &&
Math.floor(self.progress * 100) < 33
) {
setTitle("コンテンツタイトル1");
setImage("image_01.jpg");
refTitle.current!.style.color = "red";
} else if (
33 <= Math.floor(self.progress * 100) &&
Math.floor(self.progress * 100) < 66
) {
setTitle("コンテンツタイトル2");
setImage("image_02.jpg");
refTitle.current!.style.color = "blue";
} else {
setTitle("コンテンツタイトル3");
setImage("image_03.jpg");
refTitle.current!.style.color = "green";
}
},
},
});
};
useEffect(() => {
if (!didEffect.current) {
didEffect.current = true;
gsap.registerPlugin(ScrollTrigger);
fixedScroll();
}
}, []);
return (
<div className="wrapper" ref={refTrigger}>
<div className="container" ref={refElement}>
<div className="background">
<img
className="image"
src={`/assets/images/${image}`}
alt=""
/>
</div>
<div className="foreground">
<h1 className="title" ref={refTitle}>
{title}
</h1>
</div>
</div>
</div>
);
}
アニメーションの処理自体はuseEffectをつかってコンポーネントがレンダーされたタイミングで実行させますが、開発環境では2回呼び出される仕様のため、アニメーションの挙動がおかしくなってしまいます。そのため1回目だけ処理されるよう、分岐を追加しておきます。あとはHTMLをCSSでスタイリングしていきます。今回は全画面表示を想定したデザインで、背景と前面てきすとをGridレイアウトで重ねています。
.wrapper {
height: 100dvh;
width: 100%;
}
.container {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 100%;
grid-template-rows: 100%;
}
.background,
.foreground {
grid-column: 1 / 2;
grid-row: 1 / 2;
position: relative;
}
.background {
z-index: 1;
}
.foreground {
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
}
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
これでスクロール量にあわせて固定表示させたコンテンツを切り替える動きができました。実際に作成したデモはこちらにありますので、是非チェックしてみてください。
今回はReactでGSAPをつかったスクロールに連動させたアニメーションを実装するパターンについて見ていきました。useEffectの仕様など、注意したいポイントがありますので覚えておきたいですね。
categories
- WordPress(61)
- JavaScript(49)
- Vue.js(48)
- CSS(46)
- jQuery(34)
- Nuxt.js(22)
- Sass(21)
- Gulp(17)
- webpack(16)
- PHP(14)
- HTML(14)
- GSAP(11)
- React(10)
- Vite(9)
- Pug(9)
- Laravel(8)
- Cordova(8)
- Linux(7)
- Next.js(6)
- Apache(5)
- Shopify(4)
- REST API(4)
- Node.js(4)
- Smarty(3)
- Git(3)
- JSON(3)
- その他プログラミング(3)
- Google Apps API(3)
- Bootstrap(3)
- 環境構築・システム(3)
- TypeScript(2)
- EJS(2)
- RMS(2)
- Docker(2)
- Instagram API(2)
- Excel VBA(2)
- SVG(1)
- Dart(1)
- ECカートASP(1)
- Markdown(1)
- AMP(1)
- Nginx(1)
- XML(1)
- shellscript(1)
- Ruby(1)
- MySQL(1)