Carousel

シームレス型のスライダー

詳しい導入事例は導入方法を参照してください。

使い方

カルーセルにしたい要素の親に+-mod_slider-+のクラスを付与するだけでカルーセル化します。
内部要素が親要素の幅以下(スクロールが発生しない場合)時と、スマホサイズの時はカルーセル化しません。

[data-scrollber="set"]属性を追加することでスクロールバーを追加します。
*-ul class="mod_slider" data-scrollber="set"-*

[data-drag="set"]属性を追加することでドラッグでのスクロールが可能になります。
*-ul class="mod_slider" data-drag="set"-*

カルーセル化は関数で実行しているので、必ず[sliderSet()]を実行してください。
基本はページ読み込み字の実行で大丈夫ですが、別途イベントに絡めることもできます。
  • HTML
  • CSS
  • Script
.mod_slider {
  width: 100%;
  margin: 0 0 24px;
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
  -webkit-overflow-scrolling: touch;
}
.mod_slider[data-scrollber="set"] {padding: 0 0 24px;}

.mod_slider-wrap {position: relative;}
.slider-nav {
  opacity: 0;
  transition: .2s;
}
.slider-nav-btn {
  width: 32px;
  height: 32px;
  margin: auto;
  border-radius: var(--radius-round);
  background: var(--overlay);
  color: var(--bg-paper);
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  position: absolute;
  top: 0;
  bottom: 0;
  transition: .2s;
}
.slider-nav-btn:hover {background: rgb(0 0 0 / .9);}
.slider-nav-btn.prev {left: 0px;}
.slider-nav-btn.next {right: 0px;}
.slider-nav-btn.prev .ico-mui::before {content: '\e408';}
.slider-nav-btn.next .ico-mui::before {content: '\e409';}
.slider-scrollbar ,
.slider-scrollbar-btn {
  height: 16px;
  border-radius: var(--radius-round);
}
.slider-scrollbar {
  width: 100%;
  background: #d0d0d0;
  position: absolute;
  bottom: 0;
  transform: scale(.5);
}
.slider-scrollbar-btn {
  background: var(--txt-light);
  cursor: pointer;
}
.mod_slider-wrap:hover .slider-nav {opacity: 1;}
.mod_slider-wrap:hover .slider-nav-btn.prev {left: 8px;}
.mod_slider-wrap:hover .slider-nav-btn.next {right: 8px;}
.moveing .mod_slider {user-select: none;}
.moveing .slider-nav {opacity: 1;}
.moveing .slider-nav-btn.prev {left: 8px;}
.moveing .slider-nav-btn.next {right: 8px;}
var frag_slider = false;
var frag_scroll = false;
var frag_resize = false;

function sliderSet(){
  let $slider = $('.mod_slider');
  $slider.each(function(){
    let w = $win.width();
    let $li = $(this).children('li');
    let i = $li.size();
    $li.addClass('slider-li');
    if(($li.width() + 8) * i > $(this).parent().width() && w > 769 && !$(this).hasClass('set')){
      let obj = '<div class="slider-nav"><button class="slider-nav-btn prev"><i class="ico-mui"></i></button><button class="slider-nav-btn next"><i class="ico-mui"></i></button></div>';
      if($(this).data('scrollber') === 'set'){
        obj = '<div class="slider-nav"><button class="slider-nav-btn prev"><i class="ico-mui"></i></button><div class="slider-scrollbar"><div class="slider-scrollbar-btn"></div></div><button class="slider-nav-btn next"><i class="ico-mui"></i></button></div>';
      }
      $(this).addClass('set').wrap('<div class="mod_slider-wrap"></div>').parent('.mod_slider-wrap').append(obj).find('.slider-scrollbar-btn').width(100 / i + '%');
    }
  });
}

// 戻る
$bd.on({
  'mousedown': function(){
    let $slider = $(this).parents('.slider-nav').prev('.mod_slider');
    frag_slider=setInterval(function(){
      $slider.scrollLeft($slider.scrollLeft() - 12);
    },1);
  },
  'mouseup': function(){
    let $slider = $(this).parents('.slider-nav').prev('.mod_slider');
    $slider.animate({
      scrollLeft: $slider.scrollLeft() - 24
    },200, 'swing');
    clearInterval(frag_slider);
  }
}, '.slider-nav-btn.prev');

// 進む
$bd.on({
  'mousedown': function(){
    let $slider = $(this).parents('.slider-nav').prev('.mod_slider');
    frag_slider=setInterval(function(){
      $slider.scrollLeft($slider.scrollLeft() + 12);
    },1);
  },
  'mouseup': function(){
    let $slider = $(this).parents('.slider-nav').prev('.mod_slider');
    $slider.animate({
      scrollLeft: $slider.scrollLeft() + 24
    },200, 'swing');
    clearInterval(frag_slider);
  }
}, '.slider-nav-btn.next');

// スクロール同期
$('.mod_slider').scroll(function(){
  let $slideWrap = $(this).parents('.mod_slider-wrap');
  let $slide = $slideWrap.find('.mod_slider');
  let $barBtn = $slideWrap.find('.slider-scrollbar-btn');
  let disp_width = $slide.width();

  // スクロールバー移動可能量(スライダー表示幅 - スライダー幅) / スクロール可能量(スライダー全幅 - スライダー表示幅)
  let offset = $(this).scrollLeft() * (disp_width - $barBtn.width()) / ($slide.get(0).scrollWidth - disp_width);
  $barBtn.css('transform', 'translateX(' + offset + 'px)');
});

// スクロールバードラッグ
$bd.on({
  'mousedown': function(e){
    tar = $(this);
    frag_scroll = true;
    scrollbar_x = (e.pageX - tar.offset().left) * 4;
    tar.parents('.mod_slider-wrap').addClass('moveing');
  }
}, '.slider-scrollbar-btn');
$bd.on('mousemove', function(e){
  if(!frag_scroll) return;

  let $slideWrap = tar.parents('.mod_slider-wrap');
  let $slide = $slideWrap.find('.mod_slider');
  let $bar = tar.parents('.slider-scrollbar');
  let bar_left = $bar.offset().left;
  let disp_width = $slide.width();

  let scrollbar_track = disp_width - tar.width(); // スクロールバー移動可能量
  let scroll_move = ((e.pageX - bar_left) * 4 / scrollbar_track * scrollbar_track) - scrollbar_x;

  if (scroll_move < 0) {scroll_move = 0;}
  else if (scroll_move > scrollbar_track * 2) {return;}

  tar.css('transform', 'translateX(' + scroll_move + 'px)');
  $slide.scrollLeft(((tar.offset().left - bar_left) / scrollbar_track * ($slide.get(0).scrollWidth - disp_width)));
});
$bd.on('mouseup', function(){
  frag_scroll = false;
  $('.mod_slider-wrap').removeClass('moveing');
});

// リストドラッグ
$.prototype.mousedragscrollable = function(){
  let target;
  $(this).each(function(i, e){
    $(e).mousedown(function (event) {
      event.preventDefault();
      target = $(e);
      $(e).data({
        down: true,
        move: false,
        x: event.clientX,
        y: event.clientY,
        scrollleft: $(e).scrollLeft(),
        scrolltop: $(e).scrollTop(),
      });
      return false;
    });
    $(e).click(function(event){
      if($(e).data('move')){return false;}
    });
  });
  $(document)
  .mousemove(function(event){
    if($(target).data('down')){
      event.preventDefault();
      let move_x = $(target).data('x') - event.clientX;
      let move_y = $(target).data('y') - event.clientY;
      if(move_x !== 0 || move_y !== 0){
        $(target).data('move', true);
      } else {
        return;
      }
      $(target).scrollLeft($(target).data('scrollleft') + move_x);
      $(target).scrollTop($(target).data('scrolltop') + move_y);
      return false;
    }
  })
  .mouseup(function(){
    $(target).data('down', false);
    return false;
  });
};
$('.mod_slider[data-drag]').mousedragscrollable();

$win.load(function(){
  sliderSet();
});

$win.on('orientationchange , resize', function(){
  if (frag_resize !== false) {clearTimeout(frag_resize);}
  frag_resize = setTimeout(function(){
    sliderSet();
  }, 300);
});