https://aosceno.tistory.com/416
바닐라 자바스크립트 슬라이더 1.2
이전에는 id로 단 한개만의 슬라이더를 만들었다면
지금은 class로 여러개의 슬라이더를 생성할 수 있게 만들어보았다.
그리고 내가 원하는 슬라이더의 setTimeout을 clearTimeout 할 수 있도록 하였다.
자동 재생 / 멈춤 / 페이저 / 좌우 화살표 / transform값으로 좌우 슬라이딩 하는 슬라이더
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 |
'CSS&JS > ⚡Thinkers' 카테고리의 다른 글
(CSS)cornic-gradient로 파이 그래프(원 그래프) 구현하기 (0) | 2021.06.30 |
---|---|
(vanilla JS) 체크박스 전체 선택 / 전체 해제 (3) (0) | 2021.06.30 |
twitter app header처럼 vanilla JS로 스크롤에 따라 내려오고 올라가는 헤더 만들기(2) (0) | 2021.06.10 |
marquee 텍스트 효과 CSS로 구현하기 (0) | 2021.05.07 |
custom Select - 이벤트 위임으로 좀 더 깔끔하게 (0) | 2021.04.30 |