JavaScriptとGSAPを使ったボタンで複数のスライダーを切り替える方法

アニメーション
なる
なる

学習期間5ヶ月、独立後半年で月収50万を突破した「なる(@naru000006)」です。

この記事では、JavaScriptとGSAPを使ったボタンで複数のスライダーを切り替える方法方法を紹介しています。

実装すること

今回実装するアニメーションはこちらです。

今回紹介するのは、ボタンでスライダーを切り替えることができるアニメーションの実装方法です。

See the Pen クリックスライダー by narukichi06 (@narukichi06) on CodePen.

解説

  1. HTML・CSS
  2. GSAPとは
  3. JavaScript解説

HTML・CSS

スライダー部分は、CSSのキーフレームアニメーションを使用しています。

今回はこのスライダーが3種類あり、それをボタンで切り変えるアニメーションを実装していきます。

See the Pen 無限スクロール by narukichi06 (@narukichi06) on CodePen.

キーフレームアニメーションについてはこちらの記事で詳しく解説していますので、ぜひご覧ください。

GSAPとは

今回は「GSAP(ジーサップ)」というアニメーションのプラグインを使用します。

GSAP(GreenSock Animation Platform)は、ウェブ上でのアニメーションを作成するための強力なJavaScriptライブラリです。

HTML要素、SVG、Canvas、WebGLなど、さまざまなメディアタイプのアニメーションを制御するためのツールが含まれています。

今回はGSAPを使ってより自然なアニメーションを作っていきます。

GSAPの読み込み

GSAPも他のプラグイン同様CDNがあるので、bodyタグの閉じタグ直前に入れてください。

今回使用したCDNはこちらです。

//GSAP
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>

GSAP公式サイトのCDN一覧はこちらです。

「GSAP3 Install Helper」の「ScrollTrigger」にチェックを入れると自動的にCDNが下に表示されます。

Installation | GSAP | Docs & Learning
GSAPis"frameworkagnostic",thismeansitcanbeusedinReact,Webflow,Wordpress,oranyotherJS/Webframeworks.ThecoreGSAPfileandallthepluginsarejustJavascriptfiles.

JavsScript解説

まずは、今回使用するアニメーションのコードを見てみましょう。

document.addEventListener("DOMContentLoaded", function() {
    // 初期状態の設定
    setActiveAndAnimate("slider1");

    // 全てのボタンにイベントリスナーを追加
    document.querySelectorAll('.slider-click-btn').forEach(function(button) {
        button.addEventListener('click', function(event) {
            event.preventDefault();

            // クリックされたボタンのhref属性からIDを取得
            const buttonId = this.querySelector('a').getAttribute('href').slice(1);

            // 現在アクティブなボタンを取得
            const activeButtonId = document.querySelector('.slider-click-btn.active a').getAttribute('href').slice(1);

            // クリックされたボタンが既にアクティブでない場合にのみアニメーションを実行
            if (activeButtonId !== buttonId) {
                setActiveAndAnimate(buttonId);
            }
        });
    });
});

function setActiveAndAnimate(buttonId) {
    document.querySelectorAll('.slider-click-btn').forEach(function(button) {
        button.classList.remove('active');
        const link = button.querySelector('a');
        link.classList.remove('disabled');
        link.removeAttribute('disabled');
        link.style.pointerEvents = ''; // ポインターイベントを有効にする
    });

    // 選択されたボタンにactiveクラスを追加し、クリック不可に設定
    const activeButton = document.querySelector('a[href="#' + buttonId + '"]').parentNode;
    activeButton.classList.add('active');
    const activeLink = activeButton.querySelector('a');
    activeLink.classList.add('disabled');
    activeLink.setAttribute('disabled', 'disabled');
    activeLink.style.pointerEvents = 'none'; // ポインターイベントを無効にする

    const tl = gsap.timeline();

    // 現在のアクティブなslider-boxのautoAlphaを0に設定
    tl.to('.slider-box', { 
        autoAlpha: 0, 
        duration: 0.7, 
        ease: 'power2.inOut',
        onComplete: removeAnimationFloat, // アニメーション完了時に実行する関数
        onCompleteParams: ["#"+buttonId] // 現在のアクティブなslider-boxのIDをパラメータとして渡す
    });

    // 新しいアクティブなslider-boxのautoAlphaを1に設定
    tl.to('#' + buttonId, { autoAlpha: 1, duration: 0.7, ease: 'power2.inOut' }, '+=0.2');

    // animation-floatクラスの適用
    document.querySelectorAll('#' + buttonId + ' .slider-img-box').forEach(function(box) {
        tl.add(function() { box.classList.add('animation-float'); }, '-=0.7');
    });
}

// 指定されたslider-boxの子要素からanimation-floatクラスを削除する関数
function removeAnimationFloat(id) {
    document.querySelectorAll(id + ' .slider-img-box').forEach(function(box) {
        box.classList.remove('animation-float');
    });
}

このコードは「初期設定」「ボタンの設定」「スライダー切替」の3つのパートに分かれています。

初期設定

このアニメーションでは、ページ読み込み時に1つ目のスライダーが選択された状態になっています。

まず、ページ読み込み時にsetActiveAndAnimate関数を呼び出し、1つ目のスライダー(slider1)にアニメーションを適用させます。

// 初期状態の設定
    setActiveAndAnimate("slider1");

setActiveAndAnimate関数については、次の「ボタンの設定」で解説しています。

ボタンの設定

function setActiveAndAnimate(buttonId) {
    document.querySelectorAll('.slider-click-btn').forEach(function(button) {
        button.classList.remove('active');
        const link = button.querySelector('a');
        link.classList.remove('disabled');
        link.removeAttribute('disabled');
        link.style.pointerEvents = ''; // ポインターイベントを有効にする
    });

    // 選択されたボタンにactiveクラスを追加し、クリック不可に設定
    const activeButton = document.querySelector('a[href="#' + buttonId + '"]').parentNode;
    activeButton.classList.add('active');
    const activeLink = activeButton.querySelector('a');
    activeLink.classList.add('disabled');
    activeLink.setAttribute('disabled', 'disabled');
    activeLink.style.pointerEvents = 'none'; // ポインターイベントを無効にする

    const tl = gsap.timeline();

    // 現在のアクティブなslider-boxのautoAlphaを0に設定
    tl.to('.slider-box', { 
        autoAlpha: 0, 
        duration: 0.7, 
        ease: 'power2.inOut',
        onComplete: removeAnimationFloat, // アニメーション完了時に実行する関数
        onCompleteParams: ["#"+buttonId] // 現在のアクティブなslider-boxのIDをパラメータとして渡す
    });

    // 新しいアクティブなslider-boxのautoAlphaを1に設定
    tl.to('#' + buttonId, { autoAlpha: 1, duration: 0.7, ease: 'power2.inOut' }, '+=0.2');

    // animation-floatクラスの適用
    document.querySelectorAll('#' + buttonId + ' .slider-img-box').forEach(function(box) {
        tl.add(function() { box.classList.add('animation-float'); }, '-=0.7');
    });
}

かなり分量が多いので、さらに分割して解説をしていきます。

①ボタンのリセット

この箇所では、3つの切り替えボタンのリセットを行っています。

 document.querySelectorAll('.slider-click-btn').forEach(function(button) {
        button.classList.remove('active');
        const link = button.querySelector('a');
        link.classList.remove('disabled');
        link.removeAttribute('disabled');
        link.style.pointerEvents = ''; // ポインターイベントを有効にする
    });

次に紹介するコードで、選択されているボタンにactiveクラスを付与し、選択中のボタンを再度クリックできないようにしています。

このコードでは、選択されていないボタンがクリックされたとき(別のスライダーに切り替わるとき)に前回選択されていたボタンを再度クリックできるようにするためのものです。

②選択されたボタンをクリック不可にする

選択中のボタンを再度クリックすることができないように、ポインターイベントを無効化しています。

クリックしてもスライダーの種類は変わらないので、選択中のボタンはクリック不可にする方がユーザーにとって親切な設計になります。

    // 選択されたボタンにactiveクラスを追加し、クリック不可に設定
    const activeButton = document.querySelector('a[href="#' + buttonId + '"]').parentNode;
    activeButton.classList.add('active');
    const activeLink = activeButton.querySelector('a');
    activeLink.classList.add('disabled');
    activeLink.setAttribute('disabled', 'disabled');
    activeLink.style.pointerEvents = 'none'; // ポインターイベントを無効にする

スライダー切替

    const tl = gsap.timeline();

    // 現在のアクティブなslider-boxのautoAlphaを0に設定
    tl.to('.slider-box', { 
        autoAlpha: 0, 
        duration: 0.7, 
        ease: 'power2.inOut',
        onComplete: removeAnimationFloat, // アニメーション完了時に実行する関数
        onCompleteParams: ["#"+buttonId] // 現在のアクティブなslider-boxのIDをパラメータとして渡す
    });

    // 新しいアクティブなslider-boxのautoAlphaを1に設定
    tl.to('#' + buttonId, { autoAlpha: 1, duration: 0.7, ease: 'power2.inOut' }, '+=0.2');

  // 指定されたslider-boxの子要素からanimation-floatクラスを削除する関数
  function removeAnimationFloat(id) {
     document.querySelectorAll(id + ' .slider-img-box').forEach(function(box) {
        box.classList.remove('animation-float');
     });
}

GSAPを使って、ボタンがクリックされたときに以前のスライダーを非表示にし、新しいスライダーを表示させています。

また、.slider-img-boxにanimation-floatクラスを付与することで、スライドが切り替わってからスクロールがスタートするようにしています。

.slider-img-box.animation-float {
    animation: float 30s infinite linear 0.5s both;
}

@keyframes float {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(-100%);
    }
}
// animation-floatクラスの適用
    document.querySelectorAll('#' + buttonId + ' .slider-img-box').forEach(function(box) {
        tl.add(function() { box.classList.add('animation-float'); }, '-=0.7');
    });

// 指定されたslider-boxの子要素からanimation-floatクラスを削除する関数
  function removeAnimationFloat(id) {
     document.querySelectorAll(id + ' .slider-img-box').forEach(function(box) {
        box.classList.remove('animation-float');
    });

スクロールした状態からフェードインさせたい場合は上記のJSコードは不要で、slider-img-boxにそのままキーフレームアニメーションを書いてあげれば大丈夫です。

.slider-img-box {
    animation: float 30s infinite linear 0.5s both;
}

@keyframes float {
    from {
        transform: translateX(0);
    }

    to {
        transform: translateX(-100%);
    }
}

JavaScriptの学習方法

「jQueryは触れるけど、JavaScriptはちんぷんかんぷん…」

そんな過去の自分を助けてくれたのが「ステップアップJavaScript」です。

jQueryを学習した後のステップアップとしておすすめの1冊です。

JavaScriptの初歩から解説してくれるので、このJavaScript全然分からない…!という方でも安心して取り組むことができます。

ちなみに、jQueryから学習したい方はこちらの「jQuery標準デザイン講座」がおすすめです。

まとめ

WEB制作者にとって避けては通れないJavaScriptですが、HTMLやCSSなどのマークアップ言語とは違って、ガチなプログラミング言語なので学習難易度はかなり高いと思います。

そのため、1からコードを書けるようになろうとすると挫折します。

ChatGPTに聞いたりググりながら実装できればOKの精神でやっていきましょう。

今回はJavaScriptの解説をメインで行ってきましたので、もしGSAPについて詳しく知りたい方はこちらの記事をご参照ください。

コメント

タイトルとURLをコピーしました