Jqueryでフリック対応カルーセル系スライダー

提供:wiki - PCスキルの小技・忘却防止メモ
移動: 案内, 検索

jqueryでフリック対応カルーセル系スライダー。スマホとかである指でスライドさせるってヤツ。

基本

とりあえず注意事項は下記。

  • 対象をフリック対応にする
  • PC用にマウスドラッグ対応も用意する
  • 対象外でフリック・マウスドラッグを終えたときの処理も考える
  • はじっこまで来たときそれ以上、進まないようにする

※画像の縦横のサイズはできる限り揃えておく必要がある。

ソース

説明が面倒なのでソース内にコメントをいれておく。

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>フリック対応カルーセル系スライダー</title>
<style type="text/css">
ul, li {
  margin: 0;
  padding: 0;
  list-style: none;
}
.viewArea{
  width: 240px;
  height: 150px;
  margin: 0 auto;
  position: relative;
  overflow: hidden;
}
.slider{
  position: absolute;
  top: 0;
  left: 0;
  display: table;
  width: auto;
}
.slider li{
  width: 120px;
  display: table-cell;
}
</style>
<script type="text/javascript" src="jquery.min.js"></script>
</head>

<body>
  <div class="viewArea">
    <ul class="slider">
      <li><a href="#"><img src="image01.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image02.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image03.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image04.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image05.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image06.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image07.jpg" alt="image"></a></li>
      <li><a href="#"><img src="image08.jpg" alt="image"></a></li>
    </ul>
  </div>
  
<script type="text/javascript">
$(function(){
  var isTouch = ('ontouchstart' in window);
  var touched = false;
  
  //スライダー調整
  var tgElm = $(".slider");
  var elmWidth = tgElm.find("li").outerWidth(true);
  var sldWidth = ( elmWidth * tgElm.find("li").size() ) + "px";
  tgElm.css({"width":sldWidth});
  
  /**
   * ※「.slider」の外でタッチが終了したときの処理が必要。
   **/
   $(".slider").bind({
    /* タッチの開始、マウスボタンを押したとき */
    'touchstart mousedown': function(e) {
      // ページが動いたり、反応を止める
      e.preventDefault();
       
      // マウスの(開始)位置(touchmove イベントを通らず終了したときのために必ず覚えておくこと)
      this.touchX = (isTouch ? event.changedTouches[0].pageX : e.pageX);
      
      // 現在の 要素 の場所を覚えておく
      this.elmentX = $(this).position().left;
       
      // タッチ処理を開始したフラグをたてる
      touched = true;
    },
    /* タッチしながら移動、マウスのドラッグ */
    'touchmove mousemove': function(e) {
      if (!touched) {
        // 開始していない場合は動かないようにする・過剰動作の防止
        return;
      }
       
      // ページが動くのを止める
      e.preventDefault();
       
      // 移動前と移動先の座標から移動値を求め、要素の移動先の座標を取得。
      var tmpX = isTouch ? event.changedTouches[0].pageX : e.pageX;
      this.elmentX = this.elmentX - (this.touchX - tmpX );
      
      // 要素を移動させる
      $(this).css({left:this.elmentX});
      
      // 移動先(pageX)を覚えておく
      this.touchX = (isTouch ? event.changedTouches[0].pageX : e.pageX);
    },
    /* タッチの終了、マウスのドラッグの終了 */
    'touchend mouseup': function(e) {
      if (!touched) {
        // 開始していない場合は動かないようにする・過剰動作の防止
        return;
      }
      
      var tmpX = Math.ceil(this.elmentX / elmWidth) * elmWidth;
      var tmpHalf = tmpX - Math.ceil(elmWidth / 2);
      
      if ( -(Math.ceil(elmWidth / 2)) < this.elmentX) {
        this.elmentX = 0;
      }
      else if (this.elmentX < -(tgElm.width()-tgElm.parents(".viewArea").width())) {
        this.elmentX = -(tgElm.width()-tgElm.parents(".viewArea").width());
      }
      else if (tmpHalf <= this.elmentX) {
        this.elmentX = tmpX;
      }
      else {
        this.elmentX = tmpX - elmWidth;
      }
      $(this).animate({left:this.elmentX+"px"}, 500);
      
      // タッチ処理は終了したため、フラグをたたむ
      touched = false;
    },
    'click': function(e) {
      return false;
    }
  });
  
  $(document).bind("touchend mouseup", function(e){
    if (touched && e.target.getAttribute("class") != "slider") {
      if (isTouch) {
        $(".slider").trigger("touchend");
      }
      else {
        $(".slider").trigger("mouseup");
      }
    }
  });
});
</script>
</body>
</html>

※「.viewArea(240x150)」の表示エリア内に「.slider li(幅120px)」の画像を並べるって感じ。

関連項目