CSS&JS/⚡Thinkers

vanilla JS Slider 1.2 (바닐라 자바스크립트 슬라이드 1.2)

arancia_ 2021. 6. 18. 09:00

https://aosceno.tistory.com/416

 

바닐라 자바스크립트로 자동재생 되며 재생/멈춤 버튼, 페이저, 이전페이지 다음페이지 버튼 있

기본 소스는 w3school의 HOW TO 항목에서 slide show 입니다. https://www.w3schools.com/howto/howto_js_slideshow.asp 기본 예제중에 자동재생, 페이저, 이전·다음페이지 버튼, 재생 멈춤 버튼을 모두 제공하는..

aosceno.tistory.com

바닐라 자바스크립트 슬라이더 1.2

이전에는 id로 단 한개만의 슬라이더를 만들었다면

지금은 class로 여러개의 슬라이더를 생성할 수 있게 만들어보았다.
그리고 내가 원하는 슬라이더의 setTimeout을 clearTimeout 할 수 있도록 하였다.

자동 재생 / 멈춤 / 페이저 / 좌우 화살표 / transform값으로 좌우 슬라이딩 하는 슬라이더

 

vanilla JS slider 1.2 슬라이더.zip
0.93MB

 

 

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
    <title>vanilla js slider 1.2</title>
<link href="./slider.css" rel="stylesheet" type="text/css"/>
<script src="./slider.js" type="module" defer></script>
</head>
<body>
    
<h1>vanilla JS Slider 1.2</h1>
 
<section class="sect">
    <div class="wrap_slider">
        <ul class="slider">
            <li><img src="./img/0.jpg"></li>
            <li><img src="./img/1.jpg"></li>
            <li><img src="./img/2.jpg"></li>
            <li><img src="./img/3.jpg"></li>
            <li><img src="./img/4.jpg"></li>
        </ul><!-- slider -->
    </div><!-- wrap_slider -->
    <article class="pagerArea"><div class="inWrap">
        <button class="btn" data-order="prev" title="이전"></button>
        <button class="btn" data-order="next" title="다음"></button>
        <ul class="pager">
        </ul>
        <button class="btn_pause" data-order="pause" data-status="moving">PAUSE ME</button>
    </div></article><!-- pagerArea -->
</section><!-- sect -->
 
</body>
</html>
cs




CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
@charset "utf-8";
:root{
    --wid:80%;
    --inWrap:800px;
}
 
*{margin:0;padding:0;box-sizing:border-box;}li{list-style-type:none;}img{vertical-align:middle;}button{cursor:pointer;}
html,body{width:100%;min-height:100vh;background:#000;font-size:20px;color:#666;}
 
h1{ margin:1rem auto 3rem;
    text-align:center;}
 
/* 영역 */
.sect{
    display:flex;flex-direction:column;flex-wrap:wrap;
    align-items:center;
    position:relative;overflow:hidden;
    width:100%;
    margin-bottom:5rem;}
 
/* 슬라이더 */
.wrap_slider{ outline:3px solid lime;
    position:relative; overflow:hidden;
    width:var(--wid);max-width:var(--inWrap);
    aspect-ratio:16/9;}
 
.slider{
    display:flex;flex-wrap:nowrap;
    position:relative;
    transform:translateX(0);
    transition:all 1s;}
 
.slider li{
    flex:none;
    position:relative;overflow:hidden;
    width:100%;height:100%;}
 
.slider li img{
    width:100%;height:100%;object-fit:contain;}
 
/* 페이저 - 영역*/
.pagerArea{
    position:relative;
    width:100%;
    margin-top:1rem;
    background:rgba(255,255,255,.1);}
    
.pagerArea .inWrap{
    display:flex;flex-wrap:wrap;
    justify-content:center;align-items:center;
    position:relative;
    width:var(--wid);max-width:var(--inWrap);
    margin:0 auto; padding:.5rem 0;}
 
/* 페이저 - 화살표 */
[data-order="prev"],[data-order="next"]{
    display:block;position:absolute;
    width:2rem;height:2rem;
    background:rgba(255,255,255,.5);
    backdrop-filter:blur(5px);
    border:1px solid rgba(255,255,255,.5);
    border-radius:50%;
    cursor:pointer;}
 
[data-order="prev"]{left:1rem;}
[data-order="next"]{right:1rem;}
 
[data-order="prev"]::after,
[data-order="next"]::after{
    content:'';display:block;position:absolute;
    top:32%;
    width:25%;height:25%;
    border:4px solid rgba(0,0,0,.5);
    transform:rotate(45deg);
    border-radius:2px;
    pointer-events:none;}
 
[data-order="prev"]::after{
    left:40%;
    border-width:0 0 4px 4px;}
[data-order="next"]::after{
    left:28%;
    border-width:4px 4px 0 0;}
 
/* 페이저 - 개별 버튼 */
.pager{
    display:flex;flex-wrap:wrap;}
.pager li{
    display:block;
    width:.7rem;height:.7rem;
    margin:0 .25em;
    border-radius:.7rem;
    background:rgba(255,255,255,.5);
    cursor:pointer;
    transition:all .3s;}
 
.pager li.on{
    width:3rem;
    background:rgba(255,0,0,.8);}
 
/* 페이저 - 일시정지 및 다시 재생 */
.btn_pause{
    padding:.5em 1.5em; margin:0 1rem;
    background:transparent;
    border:1px solid #fff;
    color:#fff;
}
cs




slider.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import * as make from './make.js';
import * as onPager from './onPager.js';
import * as move from './move.js';
 
/* 01. pager 만들기 */
const sect = document.getElementsByClassName('sect');
for(let section of sect){make.makePager(section);}
 
/* 02. pager 선택시 동작 */
const pagerArea = document.getElementsByClassName('pagerArea');
for(let pgA of pagerArea){
    pgA.addEventListener('click',onPager.clickPager);
}
 
/* 03. auto slider 적용 */
const ul_slider = document.getElementsByClassName('slider');
 
for(let i=0; i<ul_slider.length; i++){
    setTimeout(()=>move.autoSlide(ul_slider[i],i), 3000);
}
 
/*  */
 
cs




make.js

1
2
3
4
5
6
7
8
9
10
11
12
/* 01. pager 만들기 */
export function makePager(section){
    const thisSlider = section.querySelector('.slider')
    const thisSliders = thisSlider.children;
    const pager = section.querySelector('.pager');
    for(let j=0; j<thisSliders.length; j++ ){
        const makeLI = document.createElement('LI');
        makeLI.dataset.order = j;
        if(j == 0){makeLI.classList.add('on');}
        pager.appendChild(makeLI);
    }//for
}//makePager
cs




onPager.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import * as move from './move.js';
 
let clickOBJ = {
    slider : "",
    order : "",
    idx : 0
};
 
let sect = document.getElementsByClassName('sect');
let nowSect;
 
/* 02. pager 선택시 동작 */
export function clickPager(e){
    e = e || window.event;
 
    nowSect = e.currentTarget.parentElement;
 
    clickOBJ.idx = Array.prototype.indexOf.call(sect,nowSect);
    // console.log(clickOBJ.idx);
    
    clickOBJ.order = e.target.dataset.order;
    clickOBJ.slider = e.target.parentElement.parentElement.parentElement.querySelector('.slider');
    
    if(clickOBJ.order == "" ||clickOBJ.order == undefined){return;}
    move.stopSlide(clickOBJ.idx);
    btn_pause(e);
 
 
    if(clickOBJ.order == 'prev' || clickOBJ.order == 'next'){
        move.prevNext(clickOBJ.slider,clickOBJ.order,clickOBJ.slider.children.length);    
    }else if(clickOBJ.order == 'pause'){
        if(e.target.dataset.status == "moving"){
            e.target.dataset.status = 'paused';
            return;
        }else{
            e.target.dataset.status = 'moving';
            btn_restart(e);
            move.autoSlide(clickOBJ.slider,clickOBJ.idx);
        }
    }else{
        clickOBJ.slider = e.target.parentElement.parentElement.parentElement.parentElement.querySelector('.slider');
        move.click_pager(clickOBJ.slider,clickOBJ.order,e.target);
    }
    
}//clickPager
 
 
function btn_pause(e){
    const thisBtn = e.currentTarget.getElementsByClassName('btn_pause')[0];
    thisBtn.innerText = 'RESTART';
}//btn_pause
 
function btn_restart(e){
    const thisBtn = e.currentTarget.getElementsByClassName('btn_pause')[0];
    thisBtn.innerText = 'PAUSE ME';
}//btn_restart
cs




move.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
let slObj = {
    width : 0,
    now: 0,
    move : 0,
    thisPager : "",
    onNum:0
};
 
const SLIDE_TIME = 3000;
 
/*  */
export function get_slider_status(slider){
    slObj.thisPager = slider.parentElement.parentElement.querySelector('.pager');
    slObj.width = slider.offsetWidth;
    slObj.now = window.getComputedStyle(slider).transform;
    slObj.now = slObj.now.match(/matrix.*\((.+)\)/)[1].split(', ')[4];
    slObj.now = Number(slObj.now);
}
 
/* 좌우 화살표 */
export function prevNext(slider,direc,len){
 
    get_slider_status(slider);
 
    switch(direc){
        case "prev" :
            slObj.move = slObj.now + slObj.width;
            if(slObj.move > 0){slObj.move = -(slObj.width * (len-1));}
            break;
        case "next" :
            slObj.move = slObj.now - slObj.width;
            if(slObj.move < -(slObj.width * (len-1))){slObj.move = 0;}
            break;
        default:
            break;
    }//switch
 
    slider.style.transform = `translateX(${slObj.move}px)`;
 
    slObj.onNum = Math.floor(slObj.move / slObj.width);
    on_pager(slObj.thisPager, slObj.onNum);
 
 
}//prevNext
 
 
/* 페이저 클릭시 */
export function click_pager(slider,order,target){
    order = Number(order);
    slObj.width = slider.offsetWidth;
    slider.style.transform = `translateX(${-(slObj.width * order)}px)`;
 
    const sbl = target.parentElement.children;
    for(let pg of sbl){pg.classList.remove('on');}
    target.classList.add('on');
}//click_pager
 
function on_pager(pager,num){
    const sbl = pager.children;
    for(let pg of sbl){pg.classList.remove('on');}
    sbl[num * -1].classList.add('on');
}
 
 
/* AUTO SLIDER */
export function autoSlide(slide,num){
    get_slider_status(slide);
    slObj.move = slObj.now - slObj.width;
    if(slObj.move < -(slObj.width * (slide.children.length-1))){slObj.move = 0;}
 
    slide.style.transform = `translateX(${slObj.move}px)`;
 
    slObj.onNum = Math.floor(slObj.move / slObj.width);
    on_pager(slObj.thisPager, slObj.onNum);
 
    window["myVar"+num] = setTimeout(()=>{autoSlide(slide,num)},SLIDE_TIME);
 
}//autoSlide
 
 
export function stopSlide(num){ clearTimeout(window["myVar"+num]);}
 
cs