jQueryでスライダーを作成その①

こんにちは、ユイトです(@mikiprogram)

画像やコンテンツを左右に切り替えるスライダーをshibajukuで学習しました。

学習のアウトプットとして記事に残していきます。

目次

機能紹介

今回作成するスライダーの機能を紹介します。

  • 「次へ」ボタンを押すとスライドして次の画像を表示
  • 「前へ」ボタンを押すとスライドして前の画像を表示

では、早速作っていきます!

完成コード

タブメニューになっているので切り替えると、CSS・jQueryのコードが表示されます。

完成コードはこちらです↓

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>コンテンツスライダー①</title>
    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <div class="l-container">
      <h1 class="m-pageTitle">コンテンツスライダー①</h1>
      <div class="m-sliderWrap">
        <ul class="m-slider" id="js-slider">
          <li class="js-sliderItem m-slider__item">
            <img src="images/grape.jpg" alt="ぶどう" />
          </li>
          <li class="js-sliderItem m-slider__item">
            <img src="images/apple.jpg" alt="りんご" />
          </li>
          <li class="js-sliderItem m-slider__item">
            <img src="images/lemon.jpg" alt="レモン" />
          </li>
          <li class="js-sliderItem m-slider__item">
            <img src="images/pineapple.jpg" alt="パイナップル" />
          </li>
          <li class="js-sliderItem m-slider__item">
            <img src="images/strawberry.jpg" alt="いちご" />
          </li>
        </ul>
      </div>
      <!-- /.m-sliderWrap -->
      <ul class="m-sliderNav">
        <li class="m-sliderNav__item">
          <button class="m-button --prev" id="js-sliderPrevButton">前へ</button>
        </li>
        <li class="m-sliderNav__item">
          <button class="m-button --next" id="js-sliderNextButton">次へ</button>
        </li>
      </ul>
    </div>
    <!-- /.l-container -->

    <script
      src="https://code.jquery.com/jquery-1.12.4.min.js"
      integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ="
      crossorigin="anonymous"
    ></script>
    <script src="app.js"></script>
  </body>
</html>

CodeSandBoxで簡単なデモページを作成しました!

※レスポンシブには対応していないので、恐れ入りますがPCからご覧ください。

HTML作成

スライドするためのコンテンツと、「前へ」・「次へ」ボタンを作成します。

<div class="l-container">
    <h1>コンテンツスライダー</h1>
    <div class="m-sliderWrap">
      <ul class="m-slider">
        <li class="m-slider__item">
          <img src="images/grape.jpg" alt="ぶどう">
        </li>
        <li class="m-slider__item">
          <img src="apple.jpg" alt="りんご">
        </li>
        <li class="m-slider__item">
          <img src="images/lemon.jpg" alt="レモン">
        </li>
        <li class="js-sliderItem m-slider__item">
          <img src="images/pineapple.jpg" alt="パイナップル" />
        </li>
        <li class="js-sliderItem m-slider__item">
          <img src="images/strawberry.jpg" alt="いちご" />
        </li>
      </ul>
    </div>
    <!-- /.m-sliderWrap -->
    <ul>
      <li><button>前へ</button></li>
      <li><button>次へ</button></li>
    </ul>
  </div>
<!-- /.l-container -->

a要素とbutton要素の使い分け

・別のページにジャンプする機能が必要なときは、a要素を使用します。

・表示・非表示を切り替えるときは、button要素を使用します。

※個人的な使い分けの考えです。

スライドするコンテンツを横並び

主に、以下の3点をCSSで書いていきます。

  • l-containerwidth:1000px;margin: 3em auto; を指定して中央揃えにします。
  • m-sliderdisplay:flex;でスライドするコンテンツを横並びにします。

また、画像の合計枚数分のwidthを指定します。

  • m-sliderWrapに、overflow:hidden;

見た目上、画像一枚分しか表示できないようにします。

.l-container {
    width: 1000px;
    margin: 3em auto;
}

.m-sliderWrap {
    overflow: hidden;
    /* 親要素である.l-containerの幅が800pxのため、widthを指定する必要なし */
}

.m-slider {
    display: flex;
    /* スライドする画像の合計幅を指定 */
    width: 3000px;
}

m-sliderWrapwidthについて

widthに関しては、親要素のl-containerの幅が1000pxのため、指定しなくても良いです。

理由は、ブロックレベル要素のwidthは初期値がautoだからです。

スライドの仕組みをイメージする

画像をスライドさせる方法として、positionプロパティを使用します。

m-sliderposition:relative;を指定し、

画像一枚分の幅をleftに指定すると、二番目の画像が表示されます。

また、画像二枚分の幅をleftに指定すると三番目の画像が表示されます。

今回は、この動きを「前へ」・「次へ」ボタンをクリックしたときに動的に行うため、

JavaScriptを記述していきます。

.m-slider {
   //相対配置
    position: relative;
    //画像一枚分右に移動して2番目の画像が表示される
    left: -1000px;
    display: flex;
    width: 3000px;
}

スライドのイメージ動画はこちら↓

※右下でleftの値を調整しています

「前へ」・「次へ」ボタンのクリックイベント作成

JavaScriptで操作する用のid属性をHTMLに追加

追加する要素は以下の3点です。

  • ul要素にid属性js-sliderを追加します。
  • 「前へ」のbutton要素にid属性js-sliderPrevButton を追加します。
  • 「次へ」のbutton要素にid属性js-sliderNextButon を追加します。
<div class="l-container">
    <h1 class="m-pageTitle">コンテンツスライダー</h1>
    <div class="m-sliderWrap">
      <ul class="m-slider" id="js-slider">
        <!-- 中身省略 -->
      </ul>
    </div>
    <!-- /.m-sliderWrap -->
    <!-- 省略 -->
</div>
<!-- /.l-container -->

現在何枚目の画像を表示しているかを管理するための変数を作成

「現在何枚目の画像を表示しているか」管理するためのコンテンツ番号、変数indexに0を代入します。

$(function() {
  //現在のコンテンツ番号を管理
  var index = 0;

});

「前へ」ボタンのクリックイベントを作成

まず、「前へ」ボタンをクリックするたびに、コンテンツ番号から1を引きます。

次に、js-sliderleftの値をanimate() を使って変更します。

また、アニメーションを実行中にボタンを素早くクリックすると、

クリックした回数分だけアニメーションが継続されるので

アニメーションを止めるために、animate()の前にstop() を使用します。

$(function () {
    var index = 0;
    //「前へ」ボタンをクリックした時の処理
    $("#js-sliderPrevButton").click(function() {
        //現在のコンテンツ番号から1を引く
        index -- ;
        //leftの値をアニメーションで変更
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
};

「次へ」ボタンのクリックイベントを作成

まず、「次へ」ボタンをクリックするたびに、コンテンツ番号から1を足します。

それ以降の処理は、「前へ」ボタンと一緒です。

$(function () {
    var index = 0;
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        $("#js-slider").animate({
            left: "-1000" * index
        },300);
    });
    //「次へ」ボタンをクリックした時の処理
    $("#js-sliderNextButton").click(function() {
        //現在のコンテン番号に1を足す
        index ++ ;
        //leftの値をアニメーションで変更
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
};

この時点で、

「次へ」ボタンを押すと、二枚目、三枚目と表示され、

「前へ」ボタンを押すと、三枚目、二枚目と表示され、機能としては完成しています。

しかし、今のままでは「次へ」ボタンを押し続けるとコンテンツが存在しなくても、

js-sliderが移動し続けてしまいます。「前へ」ボタンでも同様です。

そのため、コンテンツ番号を調整して、コンテンツが存在しない場所には

移動させないようにしていきます。

コンテンツが存在しない場所には、移動させない

今のままでは、コンテンツが存在しない場所でも移動できてしまうので、

以下のようにしたいと思います。

  • もしも、最初のコンテンツで「前へ」ボタンがクリックされると、

最後のコンテンツに移動させます。

  • もしも、最後のコンテンツで「次へ」ボタンがクリックされると、

最初のコンテンツに移動させます。

li要素にJavaScript操作用のclass属性を追加

li要素にJavaScript操作用のclass属性js-sliderItemを追加します。

<div class="m-sliderWrap">
   <ul class="m-slider" id="js-slider">
     <li class="js-sliderItem m-slider__item">
       <!-- 省略-->
     </li>
     <!-- 省略 -->
   </ul>
</div>
<!-- /.m-sliderWrap -->

コンテンツの合計数を取得する

コンテンツの数を使って条件分岐を使いたいので、コンテンツの数を取得します。

$(function () {
    var index = 0;
    //コンテンツの数を取得
    var slideCount = $(".js-sliderItem").length;
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
    $("#js-sliderNextButton").click(function() {
        index ++ ;
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
};

今回のコンテンツの数は、三個なので直接「3」を使って条件分岐できますが、

コンテンツの数が変わったときにメンテナンス性が悪いのでlength で取得した値を使います。

「前へ」ボタンの条件分岐

最初のコンテンツで「前へ」ボタンがクリックされると、

最後のコンテンツに移動したいので、

「現在のコンテンツ番号が0より小さいとき」のif文を書いていきます。

そして、0より小さいときは、コンテンツ番号をコンテンツ数から「1」引いた値にします。

$(function () {
    var index = 0;
    var slideCount = $(".js-sliderItem").length;
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        //コンテンツ番号が0より小さいかチェック
        if(index < 0) {
           //コンテンツ番号をコンテンツ数から1引いた値にする。
           index = slideCount -1;
         }
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
    $("#js-sliderNextButton").click(function() {
        index ++ ;
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
};

「次へ」ボタンの条件分岐

最後のコンテンツで「次へ」ボタンがクリックされると、

最初のコンテンツに移動に移動したいので、

「コンテンツ番号がコンテンツ数以上のとき」のif文を書いていきます。

そして、コンテンツ数以上のときは、コンテンツ番号を「0」にします。

$(function () {
    var index = 0;
    var slideCount = $(".js-sliderItem").length;
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        if(index < 0) {
           index = slideCount -1;
         }
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
    $("#js-sliderNextButton").click(function() {
        index ++ ;
        //コンテンツ番号がコンテンツ数以上のとき
        if(index > slideCount - 1) {
           //コンテンツ番号を0にする
           index = 0;
        }
        $("#js-slider").stop().animate({
            left: "-1000" * index
        },300);
    });
};

重複している処理を関数化する

以上で今回したかった機能は実現することはできました。

しかし、「次へ」・「前へ」ボタンのクリックイベントを見てみると、animate()の部分や

if文は関数にまとめることができそうなので、処理をまとめていきます。

目的のコンテンツまで移動させる独自関数を作成

animate() の部分は「前へ」・「次へ」ボタンのどちらも同じ処理を行なっているので、

独自関数function sliding(){・・・}にまとめます。

まとめるだけだと、処理が実行されないのでsliding()で呼び出して実行します。

$(function () {
    var index = 0;
    var slideCount = $(".js-sliderItem").length;
    //目的のコンテンツまで移動させる独自関数
    function sliding() {
     $("#js-slider").stop().animate({
         left: "-1000" * index
        },300);
    }
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        if(index < 0) {
           index = slideCount -1;
        }
        //独自関数の呼び出し
        sliding();
    });
    $("#js-sliderNextButton").click(function() {
        index ++ ;
        if(index > slideCount - 1) {
            index = 0;
        }
        //独自関数の呼び出し
        sliding();
    });
};

条件分岐をまとめる

「前へ」・「次へ」ボタンのif文もsliding() に処理できるので、まとめます。

これ以上関数にまとめることができないので、今回はこれで完成です😄

$(function () {
    var index = 0;
    var slideCount = $(".js-sliderItem").length;
    //目的のコンテンツまで移動させる独自関数
    function sliding() {
     //if文をまとめる
     if(index < 0) {
        index = slideCount -1;
     }
     //if文をまとめる
     if(index > slideCount - 1) {
        index = 0;
     }
     $("#js-slider").stop().animate({
         left: "-1000" * index
        },300);
    }
    $("#js-sliderPrevButton").click(function() {
        index -- ;
        sliding();
    });
    $("#js-sliderNextButton").click(function() {
        index ++ ;
        sliding();
    });
};

まとめ

今回は簡単なスライダーを作成しました。

重複している処理を関数にまとめて、コード量が短くなるとスッキリしていいですね!

次回は、自動でスライドする機能や画像の数が変わっても、

CSSでwidthを調整してなくて良い、メンテナンス性の高いスライダーを作りたいと思います!

最後まで読んでいただきありがとうございました🙇

shibajukuで学習中

僕の先生:@hilosiva

shibajukuのブログ:https://shibajuku.net/

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
目次
閉じる