小金井にあるWEB制作会社の備忘録

MEMORANDUM

jQueryで無限ループするスライダーにナビゲーションを設置する

以前、画面の端から端まで無限ループするスライダーを実装したのですが、そちらの応用版。
適当なところで巻き戻し、先送りをしたいとの要望があったので実装方法をメモ。

HTML

<div class="loopSlider">
<div class="loopslider__wrap">
<ul>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
<li><img src="○○○○"></li>
</ul>
</div>
</div>
<nav class="loopSlider__nav">
<ul>
<li class="toleft"><a href="">toleft</a></li>
<li class="toright"><a href="">toright</a></li>
</ul>
</nav>

<script>
$(function(){
	loopsliderPosition();
});
</script>

CSS

.loopSlider {
	overflow: hidden;
}
.loopslider__wrap {
	display: flex;
}
.loopslider__wrap ul {
	display: flex;
}
.loopslider__wrap ul li {
	width: 350px;
	height: 320px;
	padding: 0 30px 0 0;
}
.loopslider__wrap ul li img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

jQuery

$(function () {
	var LoopsliderSize = $('.loopslider__wrap ul').width();
	$('.loopslider__wrap').css({'width':LoopsliderSize * 3 +'px'}).attr('id', '-'+LoopsliderSize);
	$('.loopslider__wrap').find('ul:first').clone().appendTo('.loopSlider .loopslider__wrap');
	$('.loopslider__wrap').find('ul:first').clone().appendTo('.loopSlider .loopslider__wrap');
	var loopslider__FW = $('.loopslider__wrap ul li:first').width();

	$('.loopSlider__nav .toleft a').click(function(){
		var result = $('.loopslider__wrap').css('margin-left').replace(/px/g, '');
		var val = Number(result) - loopslider__FW;
		//停止位置を保存
		$('.loopslider__wrap').attr('id', val);
		$('.loopslider__wrap').stop().animate({'margin-left':'-='+loopslider__FW+'px'}, 'slow', 'swing', function(){
			loopsliderPosition();
		});
		return false;
	});
		
	$('.loopSlider__nav .toright a').click(function(){
		var result = $('.loopslider__wrap').css('margin-left').replace(/px/g, '');
		var val = Number(result) + loopslider__FW;
		//停止位置を保存
		$('.loopslider__wrap').attr('id', val);
		$('.loopslider__wrap').stop().animate({'margin-left':'+='+loopslider__FW+'px'}, 'slow', 'swing', function(){
			loopsliderPosition();
		});
		return false;
	});
});

function loopsliderPosition(){
	//画像一点に対して7.5秒に設定
	var Looptime = $('.loopslider__wrap ul:first li').size() * 7500;
	//ループする距離を取得
	var LoopsliderSize = $('.loopslider__wrap ul:first').width();
	//ループの開始位置(座標位置)を取得
	var loopslider__position = Number($('.loopslider__wrap').attr('id'));

	//必要に応じて開始位置を調整
	if(loopslider__position >= 0){
		loopslider__position = loopslider__position - LoopsliderSize;
	}else if(loopslider__position - LoopsliderSize <= '-'+LoopsliderSize*3){
		loopslider__position = loopslider__position + LoopsliderSize;		
	}
	$('.loopslider__wrap').css({'margin-left':+loopslider__position +'px'});
	$('.loopslider__wrap').stop().animate({'margin-left':+(loopslider__position - LoopsliderSize)+'px'}, Looptime, 'linear', function(){
		loopsliderPosition();
	});
};

クリック時に対象方向へ移動させるのは通常のクリックスライダーと同じですが、常に左方向へ移動してるため、クリックした時点でループを解除。
停止位置の座標を取得し値をidに保管してから、再度ループ処理(loopsliderPosition)を読み込むことでスライダーを再開。
この時に開始位置がオリジナル画像の範囲内に無い場合は、開始位置を調整することで途切れることのないスライダーを実装しています。

スマホのフリック対応は下記。
PC版のクリック処理の後に追記する。

jQuery

if($(window).width() < 960){
	$('.loopSlider').bind({
		'touchstart': function(e) {
			this.touchX = event.changedTouches[0].pageX;
			this.slideX = $(this).position().left;
		},
		'touchmove': function(e) {
			var moveX = this.touchX - event.changedTouches[0].pageX,
			moveY = this.touchY - event.changedTouches[0].pageY,
			moveRate = moveX / moveY;
			if(moveRate > Math.tan(15 * Math.PI/180)){
				e.preventDefault();
			}
			this.slideX = this.slideX - (this.touchX - event.changedTouches[0].pageX );
			this.accel = (event.changedTouches[0].pageX - this.touchX) * 5;
			this.touchX = event.changedTouches[0].pageX;
		},		
		'touchend': function(e){
			edge = this.slideX % top__item__slider__FW;
									
			if(edge < -50){
						
				var result = $('.loopslider__wrap').css('margin-left').replace(/px/g, '');
				var val = Number(result) - loopslider__FW;
				$('.loopslider__wrap').attr('id', val);
				$('.loopslider__wrap').stop().animate({'margin-left':'-='+loopslider__FW+'px'}, 'slow', 'swing', function(){
					loopsliderPosition();
				});
				return false;

			}else if(edge > 50){

				var result = $('.loopslider__wrap').css('margin-left').replace(/px/g, '');
				var val = Number(result) + loopslider__FW;
				$('.loopslider__wrap').attr('id', val);
				$('.loopslider__wrap').stop().animate({'margin-left':'+='+loopslider__FW+'px'}, 'slow', 'swing', function(){
					loopsliderPosition();
				});
				return false;

			}
		}
	});
}

サンプル

同一カテゴリーの記事