Chapter07 スライダー(後編)

概要と目標前回作ったスライダーを
より進化させよう。

前回作ったコンテンツスライダーをもっと汎用性の高いものに進化させましょう。

今回のゴール

RERUN

幅の自動設定 コンテンツの数に合わせて、
自動で幅を設定。

現在のコンテンツスライダーの仕様では、コンテンツが5つ以外になるとコードを変更する必要がある。
コンテンツの数が変わってもコードを変更しなくて済む仕様に変更する

幅の自動設定をしよう

width() ・・・ 要素の幅を変更したり取得したりする
$(セレクタ).width(変更する幅);
                   省略可

パラメータを省略すれば幅を取得できる

詳細はjQuery API Documentationを参照

  1. 「chapter07」 › 「slider」フォルダ内の「app.js」をテキストエディタで開く
  2. 下記を参考に、幅を取得したり変更したりする
chapter07/slider/app.js
$(function () {
  // スライドコンテンツの数を取得
  var count = $('.js-sliderItem').length;

  // スライドコンテンツの幅を取得
  var slideWidth = $('.js-sliderItem').width();

  // スライドコンテンツを横並びするために必要な幅を計算
  var totalWidth = slideWidth * count;

  // 計算した幅を指定
  $('.js-slider').width(totalWidth);

  // 現在のコンテンツ番号を変数で管理
  var index = 0;

  // 目的のコンテンツまでスライドする関数
  function sliding() {
    // 現在のコンテンツが 「0」より小さいかチェック
    if (index < 0) {
      // 「0」より小さい時
      index = count - 1;
    }

    // 現在のコンテンツが コンテンツの数以上かを確認
    if (index > count - 1) {
      // コンテンツの数より大きい
      index = 0;
    }

    // leftの値をアニメーションで変更
    $('.js-slider').animate({
      left: index * -slideWidth
    }, 300);
  }

  // 「前へ」ボタンが押されたとき
  $('.js-sliderPrevButton').click(function () {
    // 現在のコンテンツ番号に1を引く
    index--;
    sliding();
  });

  // 「次へ」ボタンが押されたとき
  $('.js-sliderNextButton').click(function () {
    // 現在のコンテンツ番号に1を足す
    index++;
    sliding();
  });
});
  1. 上書き保存
  2. 「chapter07」 › 「slider」フォルダ内の「style.css」をテキストエディタで開く
  3. 必要なくなった幅のスタイルを削除
chapter07/slider/style.css
.container {
  width: 800px;
  margin: 0 auto;
}

.slider-wrap {
  overflow: hidden;
}

.slider {
  position: relative;
  left: 0;

  margin: 0;
  padding: 0;
  list-style: none;
}

.slider-item {
  float: left;

}
  1. 上書き保存
  2. 「chapter07」 ›「slider」フォルダ内の「index.html」をブラウザで開く
  3. スライドが問題なく動作するかをチェック
ブラウザでの表示例

RERUN

自動再生に対応 setInterval()を使って、
自動再生を行う。

JavaScriptで学習したsetInterval()を用いて、
スライドが自動で行われるようにしてみる。

自動再生に対応しよう

  1. 「chapter07」 ›「slider」フォルダ内の「app.js」をテキストエディタで開く
  2. 自動再生を行うコードを追加
chapter07/slider/app.js
$(function () {
  // スライドコンテンツの数を取得
  var count = $('.js-sliderItem').length;

  // スライドコンテンツの幅を取得
  var slideWidth = $('.js-sliderItem').width();

  // スライドコンテンツを横並びするために必要な幅を計算
  var totalWidth = slideWidth * count;

  // 計算した幅を指定
  $('.js-slider').width(totalWidth);

  // 現在のコンテンツ番号を変数で管理
  var index = 0;

  // 目的のコンテンツまでスライドする関数
  function sliding() {
    // 現在のコンテンツが 「0」より小さいかチェック
    if (index < 0) {
      // 「0」より小さい時
      index = count - 1;
    }

    // 現在のコンテンツが コンテンツの数以上かを確認
    if (index > count - 1) {
      // コンテンツの数より大きい
      index = 0;
    }

    // leftの値をアニメーションで変更
    $('.js-slider').animate({
      left: index * -slideWidth
    }, 300);
  }

  // 自動再生の処理
  var timer = setInterval(function () {
    index++;
    sliding();
  }, 3000);

  // 「前へ」ボタンが押されたとき
  $('.js-sliderPrevButton').click(function () {
    // 現在のコンテンツ番号に1を引く
    index--;
    sliding();
  });

  // 「次へ」ボタンが押されたとき
  $('.js-sliderNextButton').click(function () {
    // 現在のコンテンツ番号に1を足す
    index++;
    sliding();
  });
});

答えを見る

  1. 上書き保存
  2. 「chapter07」 ›「slider」フォルダ内の「index.html」をブラウザで開く
  3. 自動再生されるかを確認
ブラウザでの表示例

RERUN

マウスオンで自動再生停止マウスがコンテンツに乗っている間は、
自動再生しないでほしい。

現在の仕様では、常に自動再生される。
コンテンツにマウスが乗っている間は自動再生を停止する仕様に変更する

マウスオンで自動再生を停止しよう

  1. 「chapter07」 ›「slider」フォルダ内の「app.js」をテキストエディタで開く
  2. スライドコンテンツにマウスが乗っている間は、自動再生を停止するコードを記述
chapter07/slider/app.js
$(function () {
  // スライドコンテンツの数を取得
  var count = $('.js-sliderItem').length;

  // スライドコンテンツの幅を取得
  var slideWidth = $('.js-sliderItem').width();

  // スライドコンテンツを横並びするために必要な幅を計算
  var totalWidth = slideWidth * count;

  // 計算した幅を指定
  $('.js-slider').width(totalWidth);

  // 現在のコンテンツ番号を変数で管理
  var index = 0;

  // 目的のコンテンツまでスライドする関数
  function sliding() {
    // 現在のコンテンツが 「0」より小さいかチェック
    if (index < 0) {
      // 「0」より小さい時
      index = count - 1;
    }

    // 現在のコンテンツが コンテンツの数以上かを確認
    if (index > count - 1) {
      // コンテンツの数より大きい
      index = 0;
    }

    // leftの値をアニメーションで変更
    $('.js-slider').animate({
      left: index * -slideWidth
    }, 300);
  }

  // 自動再生の処理
  var timer = setInterval(function () {
    index++;
    sliding();
  }, 3000);

  // マウスが乗っている時は自動再生を停止
  $('.js-slider').hover(function () {
    // マウスが乗っている時
    clearInterval(timer);
  }, function () {
    // マウスが離れた時
    timer = setInterval(function () {
      index++;
      sliding();
    }, 3000);
  });

  // 「前へ」ボタンが押されたとき
  $('.js-sliderPrevButton').click(function () {
    // 現在のコンテンツ番号に1を引く
    index--;
    sliding();
  });

  // 「次へ」ボタンが押されたとき
  $('.js-sliderNextButton').click(function () {
    // 現在のコンテンツ番号に1を足す
    index++;
    sliding();
  });
});

答えを見る

  1. 上書き保存
  2. 「chapter07」 ›「slider」フォルダ内の「index.html」をブラウザで開く
  3. 画像をクリックした時に、コンテンツが移動するかを確認
  4. ただし、コンテンツがない場所にもスライドしてしまう
ブラウザでの表示例

RERUN

使いまわしやすくする自動再生の有無や、
スピードは設定しやすくする。

今のままでもスライダーとしての機能が出来ているが、
今後様々なプロジェクトでも使いまわしやすくしておくと便利。

使いまわしやすくしよう。

  1. 「chapter07」 ›「slider」フォルダ内の「app.js」をテキストエディタで開く
  2. 下記を参考に、自動再生の有無や、スピードは変数で管理し、
    自動再生の処理は関数化する
chapter07/slider/app.js
$(function () {
  // オプション
  var speed = 300; // スライドの切り替え時間
  var delay = 3000; // 自動再生の待機時間
  var autoPlay = true; // 自動再生の有無

  // タイマー管理用変数
  var timer;

  // スライドコンテンツの数を取得
  var count = $('.js-sliderItem').length;

  // スライドコンテンツの幅を取得
  var slideWidth = $('.js-sliderItem').width();

  // スライドコンテンツを横並びするために必要な幅を計算
  var totalWidth = slideWidth * count;

  // 計算した幅を指定
  $('.js-slider').width(totalWidth);

  // 現在のコンテンツ番号を変数で管理
  var index = 0;

  // 目的のコンテンツまでスライドする関数
  function sliding() {
    // 現在のコンテンツが 「0」より小さいかチェック
    if (index < 0) {
      // 「0」より小さい時
      index = count - 1;
    }

    // 現在のコンテンツが コンテンツの数以上かを確認
    if (index > count - 1) {
      // コンテンツの数より大きい
      index = 0;
    }

    // leftの値をアニメーションで変更
    $('.js-slider').animate({
      left: index * -slideWidth
    }, speed);
  }

  // 自動再生の処理を行う関数
  function setTimer() {
    // 自動再生が有効化チェック
    if (autoPlay) {
      // 有効の時
      timer = setInterval(function () {
        index++;
        sliding();
      }, delay);
    }
  }

  // 自動再生の関数の呼び出し
  setTimer();

  // マウスが乗っている時は自動再生を停止
  $('.js-slider').hover(function () {
    // マウスが乗っている時
    clearInterval(timer);
  }, function () {
    // マウスが離れた時
    setTimer();
  });

  // 「前へ」ボタンが押されたとき
  $('.js-sliderPrevButton').click(function () {
    // 現在のコンテンツ番号に1を引く
    index--;
    sliding();
  });

  // 「次へ」ボタンが押されたとき
  $('.js-sliderNextButton').click(function () {
    // 現在のコンテンツ番号に1を足す
    index++;
    sliding();
  });
});
  1. 上書き保存
  2. 「chapter07」 ›「slider」フォルダ内の「index.html」をブラウザで開く
  3. スライドが問題なく機能しているかを確認。
    (オプションの設定値を自由に変えて試してみる)
ブラウザでの表示例

RERUN

練習問題 スライダーにマウスが乗ってる時、
ボタンを非表示にしよう。

スライダーにマウスが乗ってる時は、「前へ」、「次へ」ボタンを非表示にしてください。
なお、その際スライダーやボタンのCSSの自由にデザインして下さい。

ブラウザでの完成例

RERUN

解答例
chapter07/slider/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>コンテンツスライダー</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <h1>コンテンツスライダー</h1>

  <div class="container">
    <div class="slider-area">
      <div class="slider-wrap">
        <ul class="js-slider slider">
          <li class="js-sliderItem slider-item">
            <img src="images/photo-sea.jpg" alt="きれいな海">
          </li>
          <li class="js-sliderItem slider-item">
            <img src="images/photo-mountain.jpg" alt="きれいな山">
          </li>
          <li class="js-sliderItem slider-item">
            <img src="images/photo-sky.jpg" alt="きれいな空">
          </li>
          <li class="js-sliderItem slider-item">
            <img src="images/photo-river.jpg" alt="きれいな川">
          </li>
          <li class="js-sliderItem slider-item">
            <img src="images/photo-town.jpg" alt="きれいな街">
          </li>
        </ul>
      </div>
      <!-- /.slider-wrap -->

      <ul class="js-sliderNav slider-nav">
        <li>
          <button class="js-sliderPrevButton slider-button slider-prev">
            <span class="screen-reader-text">前へ</span>
          </button>
        </li>
        <li>
          <button class="js-sliderNextButton slider-button slider-next">
            <span class="screen-reader-text">次へ</span>
          </button>
        </li>
      </ul>
    </div>
    <!-- /.slider-area -->
  </div>
  <!-- /.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>
chapter07/slider/app.js
$(function () {
  // オプション
  var speed = 300; // スライドの切り替え時間
  var delay = 3000; // 自動再生の待機時間
  var autoPlay = true; // 自動再生の有無

  // タイマー管理用変数
  var timer;

  // スライドコンテンツの数を取得
  var count = $('.js-sliderItem').length;

  // スライドコンテンツの幅を取得
  var slideWidth = $('.js-sliderItem').width();

  // スライドコンテンツを横並びするために必要な幅を計算
  var totalWidth = slideWidth * count;

  // 計算した幅を指定
  $('.js-slider').width(totalWidth);

  // 現在のコンテンツ番号を変数で管理
  var index = 0;

  // 目的のコンテンツまでスライドする関数
  function sliding() {
    // 現在のコンテンツが 「0」より小さいかチェック
    if (index < 0) {
      // 「0」より小さい時
      index = count - 1;
    }

    // 現在のコンテンツが コンテンツの数以上かを確認
    if (index > count - 1) {
      // コンテンツの数より大きい
      index = 0;
    }

    // leftの値をアニメーションで変更
    $('.js-slider').animate({
      left: index * -slideWidth
    }, speed);
  }

  // 自動再生の処理を行う関数
  function setTimer() {
    // 自動再生が有効化チェック
    if (autoPlay) {
      // 有効の時
      timer = setInterval(function () {
        index++;
        sliding();
      }, delay);
    }
  }

  // 自動再生の関数の呼び出し
  setTimer();

  // マウスが乗っている時は自動再生を停止
  $('.js-slider').hover(function () {
    // マウスが乗っている時
    clearInterval(timer);

    // ナビをフェードアウト
    $('.js-sliderNav').fadeOut(300);
  }, function () {
    // マウスが離れた時
    setTimer();

    // ナビをフェードイン
    $('.js-sliderNav').fadeIn(300);
  });

  // 「前へ」ボタンが押されたとき
  $('.js-sliderPrevButton').click(function () {
    // 現在のコンテンツ番号に1を引く
    index--;
    sliding();
  });

  // 「次へ」ボタンが押されたとき
  $('.js-sliderNextButton').click(function () {
    // 現在のコンテンツ番号に1を足す
    index++;
    sliding();
  });
});
chapter07/slider/style.css
body {
  background-color: #eee;
}

h1 {
  text-align: center;
}

.container {
  width: 800px;
  margin: 0 auto;
}

.slider-area {
  position: relative;
  padding: .5em;
  background-color: #fff;
  box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
}

.slider-wrap {
  overflow: hidden;
}

.slider {
  position: relative;
  left: 0;
  margin: 0;
  padding: 0;
  list-style: none;
}

.slider-item {
  float: left;
}

.slider-item img {
  vertical-align: bottom;
}

.slider-nav {
  padding: 0;
  margin: 0;
  list-style: none;
}

.slider-button {
  position: absolute;
  top: 0;
  bottom:0;
  margin: auto 0;
  width: 5em;
  height: 5em;
  border: none;
  border-radius: 50%;
  background-color: rgba(0 ,0, 0, 0.5);
  box-shadow: 0 0 16px rgba(0, 0, 0, 0.3);
  cursor: pointer;
  outline: none;
  transition: all .3s ease-in-out;
}

.slider-button:before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  margin: auto;
  width: 1em;
  height: 1em;
  border: 2px solid #fff;
  transform: rotate(45deg);
}

.slider-button:hover {
  background-color: rgba(0 ,0, 0, 0.9);
}

.slider-prev {
  left: -2.5em;
}

.slider-prev:before {
  border-top: none;
  border-right: none;
  left: .5em;
}

.slider-next {
  right: -2.5em;
}

.slider-next:before {
  border-bottom: none;
  border-left: none;
  right: .5em;
}

.screen-reader-text {
  clip: rect(1px, 1px, 1px, 1px);
  position: absolute !important;
  height: 1px;
  width: 1px;
  overflow: hidden;
}

解答例は全問題のチェックボックスが on になるとご覧いただけます。

まとめ JavaScriptの知識を組み合わせると
さらにいろんなことができるようになる。

JavaScriptの知識とjQueryの知識が合わされば表現の幅が広がる。