JavaScriptで、スワイプでもボタンでもスライドできるスライダーを作成

現在Webサイトを作成する場合、マルチデバイス対応が必要になります。今回は、JavaScriptで、スワイプでもボタンでもスライドできるスライダーを作成する方法を紹介します。

コード

touchstart、touchendアクションを使用して、作成しています。

<div id="container">
	<ul id="content1" >
		<li class="slider active">1</li>
		<li class="slider non-active">2</li>
		<li class="slider non-active">3</li>
		<li class="slider non-active">4</li>
		<li class="slider non-active">5</li>
	</ul>
	<div id="prev-btn"></div>
	<div id="next-btn"></div>
</div>
ul{
	list-style: none;
	flex-wrap: nowrap;
}
#content1 {
    width: 100vw;
	height: 500px;
   background: orange;
  }
#content1 li{
	position:absolute;
    min-width: 100vw;
	height: 500px;
	display: block;
	align-content: center;
	text-align: center;
	font-size: 2em;
	vertical-align: middle;
	top: 0;
	left: 0;
  }
#content1 li:first-child{
	background: #fff;
	left: 0;
}
#content1 li:nth-child(2){
	background: yellow;
}
#content1 li:nth-child(3){
	background: green;
}
#content1 li:nth-child(4){
	background: blue;
}
#content1 li:nth-child(5){
	background: #ddd;
}
#content1 li.slider.active{
	z-index: 2;
}
#content1 li.slider.non-active{
	z-index: -2;
}
#container{
	width: 100vw;
	height: 500px;
	overflow: hidden;
	position: relative;
}
#prev-btn, #next-btn{
	width: 40px;
	height: 40px;
	position: absolute;
	background: rgba(255,255, 255, 0.5);
	z-index: 3;
	cursor: pointer;
	transform: translateY(-50%)
}
#prev-btn{
	top: 50%;
	left: 0;
}
#prev-btn::before, #next-btn::before{
	content: '';
	width: 10px;
	height: 10px;
	border-top: solid 1px #000;
	border-left: solid 1px #000;
	position: absolute;
}
#next-btn{
	top: 50%;
	right: 0;
}
#prev-btn::before{
	top: 50%;
	left: 55%;
	transform: translate(-50%, -50%) rotate(-45deg);
}
#next-btn::before{
	top: 50%;
	left: 45%;
	transform: translate(-50%, -50%) rotate(135deg);
}
const slideConatner = document.querySelector('#content1');
const slide = document.querySelectorAll('.slider');
const slideCount = slide.length;
const nextBtn = document.querySelector('#next-btn');
const prevBtn = document.querySelector('#prev-btn');

function lowerSlider(){
	for(let i = 0; i < slide.length; i++){
		if(slide[i].classList.contains('active')){
			const lowerSlideCount = (slideCount + i - 1) % slideCount;
			slide[lowerSlideCount].animate(
			  	{
			  		translate: ['-100vw 0', '0 0']
		  	  	},
			  	{
					duration: 800,
					easing: 'ease',
				  	fill: 'forwards'
			  	}
			);
			 slide[i].animate(
			  	{
			  		translate: [ '0 0','100vw 0']
		  	  	},
			  	{
					duration: 800,
					easing: 'ease',
				  	fill: 'forwards'
			  	}
			);
			slide[lowerSlideCount].classList.remove('non-active');
			slide[lowerSlideCount].style.pointerEvents = ('none');
			nextBtn.style.pointerEvents = ('none');
			prevBtn.style.pointerEvents = ('none');
		   	slide[lowerSlideCount].classList.add('active');
		   	slide[i].classList.remove('active');
			slide[i].style.pointerEvents = ('none');
			setTimeout(() => {
				slide[i].classList.add('non-active');
				slide[lowerSlideCount].style.pointerEvents = ('auto');
				nextBtn.style.pointerEvents = ('auto');
			    prevBtn.style.pointerEvents = ('auto');
			}, 800);
			break;
		} 
	}
}

function upperSlider(){
	for(let i = 0; i < slide.length; i++){
		if(slide[i].classList.contains('active')){	 
			const upperSlideCount = ( i + 1 ) % slideCount;
			slide[upperSlideCount].animate(
			  	{
			  		translate: ['100vw 0','0 0']
		  	  	},
			  	{
					duration: 800,
					easing: 'ease',
				  	fill: 'forwards'
			  	}
			);
			slide[i].animate(
			  	{
			  		translate: ['0 0','-100vw 0']
		  	  	},
			  	{
					duration: 800,
					easing: 'ease',
			  		fill: 'forwards'
			 	}
			);
			slide[upperSlideCount].classList.remove('non-active');
			slide[upperSlideCount].style.pointerEvents = ('none');
			nextBtn.style.pointerEvents = ('none');
			prevBtn.style.pointerEvents = ('none');
		   	slide[upperSlideCount].classList.add('active');
		   	slide[i].classList.remove('active');
			slide[i].style.pointerEvents = ('none');
			setTimeout(() => {
				slide[i].classList.add('non-active');
				slide[upperSlideCount].style.pointerEvents = ('auto');
				nextBtn.style.pointerEvents = ('auto');
			   	prevBtn.style.pointerEvents = ('auto');
			}, 800);
			break;
		}
	}
}

var startX = null;
var endX = null;

window.addEventListener('load', function(){
	for(let i = 0; i < slide.length; i++){ 
		// スワイプ/フリック
     	slide[i].addEventListener('touchmove', logSwipe);
      	// タッチ開始
      	slide[i].addEventListener('touchstart', logSwipeStart);
      	// タッチ終了
      	slide[i].addEventListener('touchend', logSwipeEnd);
	}
 });

function logSwipeStart(event) {
	event.preventDefault();
	startX = event.touches[0].pageX;
}

function logSwipe(event) {
	event.preventDefault();
	endX = event.touches[0].pageX;
}

function logSwipeEnd(event) {
	event.preventDefault();
	if( 0 < (endX - startX) ) {
		lowerSlider();
    } else {
		upperSlider();
    }
}

nextBtn.addEventListener('click', ()=> {
	upperSlider();
});
 
prevBtn.addEventListener('click', ()=> {
	lowerSlider();
});

以上で今回の説明は終了です。SP用にスワイプできるようにすると便利ですね。インジケーターやワイプアクションなどを組み合わせて、いろいろなデザインができます。

RECOMMEND

CONTACT

Webサイト作成は、是非
CXG DESIGNへご検討ください。