GSAPで無限ループするWEBページの作成方法【あのSNSも同じ仕組み?】

りょーすけ
りょーすけ

スクロールすると無限に続くWEBサイトを見たんだけどあれどういう仕組み!?

GSAP MAN
GSAP MAN

GSAPのScrollTrigger使ったら近いことが実現できるかもよ!?

以前Twitterでも話題になったWEBサイト「POLA 2029年ビジョン」イラストがグニャングニャン動く所など魅了する所が多いですが特に気になったのはどこまでスクロールしても必ず同じアニメーションが再開されるというところです

これGSAPのScrollTriggerでもできないかなとスクロールが無限に続く機能を作ってみました

デモ

まずはこちらのデモをご覧ください。しばらくスクロールしても途切れることなく永遠に続いていきます

See the Pen createElement & gsap ScrollTrigger by りょーすけ (@s_ryosuke_1242) on CodePen.

HTML

まずはHTMLを見てみましょう

<div class="container">
    <section class="section section01">
        <h1>セクション1</h1>
    </section>
    <section class="section section02">
        <h1>セクション2</h1>
    </section>
    <section class="section section03">
        <h1>セクション3</h1>
    </section>
</div>

先程のデモを見る限り果てしなく長いHTMLを書いているのでは!?と想像した方もいるかもしれませんがそうではありません。

セクションは3つのみです。仕組みはやはりJavaScriptにありそうですね

CSS

次にCSSです。特に変わったところはなくただスタイルを適用しているだけです

*{
    margin: 0;
    padding: 0;
}
.section{
    width: 100%;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
}
.section01{
    background-color: crimson;
}
.section02{
    background-color: #333;
}
.section03{
    background-color: skyblue;
}

JavaScript

次にJavaScriptです。今回はScrollTriggerを用いるため忘れずにCDNによるダウンロード等を行ってください。

gsap.registerPlugin(ScrollTrigger);

const container = document.querySelector(".container");//コンテナ要素を取得して代入
// 色を格納
const colors = [
    "#DC143C",// crimson
    "#333333",// black
    "#87CEEB",// skyblue
];

let panelNum = document.querySelectorAll('.section').length;//最初のセクション数を取得
const createSection = (index) => {
    const section = document.createElement("section");// sectionタグを持つ要素を作成
    const h1 = document.createElement("h1");// h1タグを作成
    container.appendChild(section);// コンテナ要素の中に追加
    section.appendChild(h1);// セクション要素の中に追加
    h1.innerHTML = `セクション${index+1}`;// テキスト挿入
    gsap.set(section, {
        backgroundColor: colors[index % 3],//背景色設定
        className: `section`//クラス名の指定
    });
};

ScrollTrigger.create({
    trigger: container,// トリガー位置指定
    start: "top top",// 処理スタート位置設定
    end: "bottom bottom",// 処理終了位置設定
    onUpdate: (self) => {// スクロールする度に呼び出し
        let progress = self.progress.toFixed(2);// 小数第二位まで有効に
        if (progress >= 0.9 && self.direction === 1) {
            createSection(panelNum++);
            ScrollTrigger.refresh();// 位置の再計算
        }
    },
});

各行にコメント文を記載しているので一つ一つ追っていけば理解ができるかと思います

次々にセクションが登場する仕組み

これは12行目~22行目のcreateSection関数によってセクションが次々に登場するような処理が行われる定義がされています

特に13行目のJavaScriptのメソッド.createElementによってsectionタグが生成されているところが肝です

関数となっているためこのcreateElement関数が呼び出される度にsectionタグを生成してコンテナ要素の中に追加、さらにはGSAPによってbackgroundColorとクラス名を付与しているという一連の流れを自動で行ってくれます

セクションを生成するタイミング

ではこのセクションを追加する関数.createElementですがどのタイミングで呼び出されているのでしょうか?

呼び出すタイミングはGSAPのScrollTriggerにて制御しております。ScrollTriggerに関する記述は24行~35行目です

大事なのはコールバック関数onUpdateです。これはスクロールするたびに呼び出される関数となっています

なのでスクロールするたびに29行目~32行目の処理が走ります

if文の条件式にもあるprogressですが英単語の意味の通りアニメーションの進捗率を示しており0から始まり1の値で終わります

つまり条件式の中はアニメーションの進捗率が0.9(90%)以上 かつ スクロールの方向が下方向であったときに.createElement関数を呼び出すという処理となっています

まとめ

いかがだったでしょうか。

JavaScriptのメソッドであるHTMLを生成する.createElementやHTML要素を挿入する.appendChildを用いてセクションを追加する関数を作り、GSAPのScrollTriggerで生成タイミングをコントロールしているという大まかな流れを読み解いていきました。

この無限に要素が生成されるのはSNS、特にTwitterなどの例が分かりやすいのではないでしょうか

ぜひ開発ツールを開いていただきスクロールするごとに要素が足されていくのを確認してみてください。コーダーからフロントエンドエンジニアに一歩近づくことができると思います

最後までご覧いただきありがとうございました!またね~!