LoginSignup
4
5

More than 5 years have passed since last update.

スライダー機能のスクロールはOSにおまかせしたほうがいいと思う

Last updated at Posted at 2015-09-23

特にタッチ操作ができるデバイスではJSでスクロール機能を提供するより、ブラウザそのもののスクロール機能を利用したほうがよいと思う。
思ったのでjQueryでささっと書いてみた。

サンプル

http://codepen.io/blurblue/pen/avmzGj
スマホで「1x」で見るとちょうどいいかと。

タッチデバイスでは overflow: auto; にして、それ以外では overflow: hidden; にしてスクロール機能を提供してもよいかもしれない(PCで見るとスクロールバーがかっちょわるい)。
なんにしろ、touchstartからtouchmoveやら何やらを拾ってスクロール機能を提供するのはすごく無駄だと思った次第。
iOS、Androidだときれいにスクロールバーが消えてくれるので全然見やすいし、このほうが断然実装が楽で軽い。

以下必要部分だけのコード。
細かいところはcodepenに。

HTMLコード

<div class="slider_wrapper">
  <p class="slider_btn prev js-slider-prev">prev</p><!--
  --><div class="slider js-slider">
    <ul class="slider_body js-slider-body">
      <li class="slider_item">item1</li><li class="slider_item">item2</li><li class="slider_item">item3</li><li class="slider_item">item4</li><li class="slider_item">item5</li>
    </ul>
  </div><!--
  --><p class="slider_btn next js-slider-next">next</p>
</div>

CSSコード

.slider_wrapper {
  width: 320px;

  .slider {
    display: inline-block;
    border: 1px solid #aaa;
    width: 180px;
    padding: 1em 0;
    vertical-align: middle;
    overflow-x: auto;
  }

  .slider_body {
    width: 10000px; /* sample */
    box-sizing: border-box;
  }

  .slider_item {
    display: inline-block;
    width: 160px;
    margin-left: 10px;
    padding: 1em 0;
    background-color: #ccc;
    vertical-align: middle;
    text-align: center;
    &:first-child {
      margin-left: 0;
    }
  }

  .slider_btn {
    position: relative;
    display: inline-block;
    width: auto;
    margin: 0 0.4em;
    border: 1px solid #aaa;
    background-color: #eee;
    padding: 0.5em;
    color: #444;
    vertical-align: middle;
    cursor: pointer;
    &:hover {
      background-color: #fafafa;
    }
    &.prev {
      padding-left: 1.5em;
      &:before {
        content: "<";
        display: block;
        position: absolute;
        left: 0.5em;
      }
    }
    &.next {
      padding-right: 1.5em;
      &:before {
        content: ">";
        display: block;
        position: absolute;
        right: 0.5em;
      }
    }
    &.disabled {
      color: #fff;
      background-color: #aaa;
      cursor: default;
    }
  }
}

jQueryコード

var Slider = {};
Slider.sliderBody = $('.js-slider');
Slider.items = Slider.sliderBody.find('li');
Slider.itemWidth = Slider.items.eq(0).width();
Slider.itemMargin = parseInt(Slider.items.eq(1).css('margin-left'), 10);
Slider.btnNext = $('.js-slider-next');
Slider.btnPrev = $('.js-slider-prev');
Slider.moveVal = function(which){
  var defaultVal = Slider.itemWidth + Slider.itemMargin,
      left = Slider.sliderBody.scrollLeft();
  var val = 0;
  if(left%defaultVal == 0){
    if(which == 'next'){
      val =  left + defaultVal;
    } else {
      val = left - defaultVal;
    }
  } else {
    if(which == 'next'){
      val = (Math.floor(left/defaultVal) + 1) * defaultVal;
    } else {
      val = (Math.floor(left/defaultVal)) * defaultVal;
    }
  }
  return val;
};

Slider.btnControll = function(){
  var left = Slider.sliderBody.scrollLeft(),
      next =  Slider.sliderBody.width() + left < Slider.scWidth,
      prev = left > 0;
  if(next){
    Slider.btnNext.removeClass('disabled');
  } else {
    Slider.btnNext.addClass('disabled');
  }
  if(prev){
    Slider.btnPrev.removeClass('disabled');
  } else {
    Slider.btnPrev.addClass('disabled');
  }
};

/* next */
Slider.onNext = function(){
  var moveTo = Slider.moveVal('next');
    Slider.sliderBody.scrollLeft(moveTo);
  Slider.btnControll();
}

/* prev */
Slider.onPrev = function(){
  var moveTo = Slider.moveVal('prev');
  Slider.sliderBody.scrollLeft(moveTo);
  Slider.btnControll();
}

/* init */
Slider.init = function(){
  Slider.scWidth = Slider.items.length * (Slider.itemWidth + Slider.itemMargin) - Slider.itemMargin;
  Slider.sliderBody.find('.js-slider-body').width(Slider.scWidth + 'px');
  $('body').on('load', Slider.btnControll());
  Slider.sliderBody.scroll(function(){
    Slider.btnControll();
  });

  $('.js-slider-prev').on(_EVENT_TOUCH.START, function(){
    if(!$(this).hasClass('disabled')){
      Slider.onPrev();
    }
  });

  $('.js-slider-next').on(_EVENT_TOUCH.END, function(){
    if(!$(this).hasClass('disabled')){
      Slider.onNext();
    }
  });
};

Slider.init();

前・次ボタンのアクションとかは簡素化してアニメーションとかは省きました。

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5