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

  • WebDesign
  • 現在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用にスワイプできるようにすると便利ですね。インジケーターやワイプアクションなどを組み合わせて、いろいろなデザインができます。