Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

Leeyanggoo

[JS] 자바스크립트 슬라이드 6!! 버튼으로 슬라이드 넘기기! 본문

2023/JavaScript

[JS] 자바스크립트 슬라이드 6!! 버튼으로 슬라이드 넘기기!

Leeyanggoo 2023. 4. 13. 19:29

 

 

 

 

 

 

#header ul a:hover {
    background-color: #000;
    color: #fff;
    transform: scale(1.2);
    transition: all 0.5s;
}
#header li {
    margin: 0 2px;
}

/* slider__wrap */
.slider__wrap {
    width: 100%;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
}
.slider__img {
/* 이미지가 보이는 영역 */
    position: relative;
    width: 800px;
    height: 520px;
    overflow: hidden;
}
.slider__inner {
/* 전체 이미지를 감싸고 있는 박스 : 움직이는 영역 */
    display: flex;
    flex-wrap: wrap;
    width: 4800px;
    height: 520px;
}
.slider {
/* 개별적인 이미지 */
    position: relative;
    width: 800px;
    height: 520px;
}
.slider__btn a {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 50px;
    height: 50px;
    background-color: #fff;
    line-height: 50px;
    text-align: center;
    transition: all 0.3s ease;
}
.slider__btn a:hover {
    border-radius: 50%;
    background-color: #000;
    color: #fff
}
.slider__btn a.prev {
    left: 0;
}
.slider__btn a.next {
    right: 0;
}
.slider__dot {
    position: absolute;
    left: 50%;
    bottom: 30px;
    transform: translateX(-50%);
}
.slider__dot .dot {
    width: 20px;
    height: 20px;
    background-color: rgba(255,255,255,0.5);
    display: inline-block;
    border-radius: 50%;
    text-indent: -9999px;
    transition: all 0.2s;
    margin: 2px;
}
.slider__dot .dot.active {
    background-color: rgba(255,255,255,1);
}
.slider__dot .dot:hover {
    border: 2px solid #000;
}

 

<main id="main">
    <div class="slider__wrap">
        <div class="slider__img">
            <div class="slider__inner">
                <div class="slider s1"><img src="./img/sliderEffect06-min.jpg" alt="이미지1"></div>
                <div class="slider s2"><img src="./img/sliderEffect07-min.jpg" alt="이미지2"></div>
                <div class="slider s3"><img src="./img/sliderEffect08-min.jpg" alt="이미지3"></div>
                <div class="slider s4"><img src="./img/sliderEffect09-min.jpg" alt="이미지4"></div>
                <div class="slider s5"><img src="./img/sliderEffect10-min.jpg" alt="이미지5"></div>
            </div>
        </div>
        <div class="slider__btn">
            <a href="#" class="prev" title="이전 이미지">prev</a>    <!--title은 웹 접근성을 위함임-->
            <a href="#" class="next" title="다음 이미지">next</a>
        </div>
        <div class="slider__dot">
            <!-- <a href="#" class="dot active">이미지1</a>
            <a href="#" class="dot">이미지2</a>
            <a href="#" class="dot">이미지3</a>
            <a href="#" class="dot">이미지4</a>
            <a href="#" class="dot">이미지5</a> -->
        </div>
    </div>
</main>

 

이번 예제는 각각의 슬라이드가 버튼(prev)과 닷(dot)을 눌렀을 때 가로로 넘어가는 형태입니다.

slider__inner의 div의 width 값을 모든 슬라이드 width 값의 총합으로 설정했습니다.

slider__img에 overflow: hidden을 주어 넘치는 슬라이드가 가려지도록 설정했습니다.

 

dot의 개수는 슬라이드의 총 개수와 같아야 하기 때문에 HTML에서 만들지 않고, 자바스트립트 코드로 작성합니다.

이렇게 하면 코드가 계속 재활용이 가능한 코드가 되겠죠?

 

스크립트로 HTML 요소를 만들어보자!!

 

Javascript

// 선택자
const sliderWrap = document.querySelector(".slider__wrap");
const sliderImg = sliderWrap.querySelector(".slider__img");     //보여지는 영역
const sliderInner = sliderWrap.querySelector(".slider__inner"); //움직이는 영역
const slider = sliderWrap.querySelectorAll(".slider");          //개별 이미지
const sliderDot = sliderWrap.querySelector(".slider__dot")      //닷메뉴
const sliderBtn = sliderWrap.querySelectorAll(".slider__btn a") //벝은

let currentIndex = 0;                               //현재 보이는 이미지
let sliderCount = slider.length;                    //이미지 개수
let sliderInterval = 2000;  //이미지 변경 간격
let sliderWidth = slider[currentIndex].offsetWidth; //이미지 가로값
let dotIndex = "";

//닷 메뉴를 슬라이드 개수만큼 만들기
function init(){
    slider.forEach(()=> dotIndex += "<a href='#' class='dot'>이미지</a>");
        sliderDot.innerHTML = dotIndex;

        //첫 번째 닷 메뉴한테 활성화
        sliderDot.firstChild.classList.add("active")
};
init();

 

먼저 선택자로 작성한 HTML의 요소를 선택합니다.

const slider = sliderWrap.querySelectorAll(".slider")는 HTML에서 작성한 모든 슬라이드이므로, 우리가 생성해야 할 dot 메뉴의 개수가 됩니다.

let dotIndex = "";는 dot의 초기 개수 세팅을 위해 공란으로 설정합니다.

init() 함수는 slider에 forEach를 사용해 슬라이더의 개수만큼 dotIndex에 dot의 HTML 코드인 <a href='#' class='dot'>이미지</a>를 입력합니다.

따라서 dotIndex는 슬라이더 개수만큼 dot의 HTML을 담고 있는 변수이므로 dot 메뉴의 부모 div 선택자인 sliderDot에 innerHTML을 이용해 입력합니다.

또한 첫 번째 dot는 활성화되었음을 알리기 위해 firstChild(첫 번째 자식 요소를 선택)와 classList.add()를 이용해 "active" class를 넣어줍니다.

 

이미지 이동시키기

//이미지 이동시키기
function gotoSlider(num){
    sliderInner.style.transition = "all 400ms";
    sliderInner.style.transform = "translateX("+ -sliderWidth * num +"px)";
    currentIndex = num;

    //닷 메뉴 활성화
    let dotActive = document.querySelectorAll(".slider__dot .dot")
        dotActive.forEach((active)=> active.classList.remove("active"));
        dotActive[num].classList.add("active");
};

//버튼을 클릭했을 때
sliderBtn.forEach((btn, index) => {
    btn.addEventListener("click", ()=>{
        let prevIndex = (currentIndex + (sliderCount-1)) % sliderCount;
        let nextIndex = (currentIndex + 1) % sliderCount;

        if(btn.classList.contains("prev")){ //contains = 해당 속성 있는지 검사
            gotoSlider(prevIndex);
        } else {
            gotoSlider(nextIndex);
        }
    });
});

 

gotoSlider() 함수는 num이라는 매개변수를 받아 슬라이더의 width에 곱해서 슬라이드 개수만큼 총 width에서 빼줍니다.

또한 init() 함수를 이용해 생성한 각각의 dot을 dotActive에 담고, forEach문을 이용해 모든 dot에 할당된 "active" class를 지지웁니다.

num은 슬라이더와 dot의 index가 되므로, 해당 슬라이더와 dot에 다시 active를 넣어줍니다.

 

이제 gotoSlider() 함수에 들어갈 매개변수 num을 어디서 가져올지 정해야 합니다.

먼저 버튼을 누를 때마다 슬라이더가 넘어가야 하므로, 이벤트 메서드를 활용해야 합니다.

앞서 선택자에서 버튼을 가져온 sliderBtn을 forEach문을 이용해 각각의 요소에 addEventListener()를 이용합니다.

gotoSlider() 함수에서 매개변수 num의 값을 변경하여 width 값을 빼고 있으므로, prevIndex와 nextIndex에 변화하는 currentIndex의 값을 할당하여 이용해 매개변수로 활용합니다.

classList.contains() 메서드는 HTML 요소의 class 속성에 특정 클래스가 포함되어 있는지 여부를 확인하는 메서드입니다.

만약 "prev"라는 class 속성이 있다면 prevIndex의 값을 gotoSlider() 함수의 매개변수로 넘기고, 아닌 경우는 next 버튼이므로 매개변수로 nextIndex를 넘기게 됩니다.

 

dot을 클릭했을 때!

//닷 클릭 이벤트
let dotClick = document.querySelectorAll(".slider__dot .dot");
dotClick.forEach((dot, index)=>{
    dot.addEventListener("click", ()=>{
        gotoSlider(index);
    });
});

 

앞선 gotoSlider() 함수에서 선언한 dotActive는 지역변수이기 때문에 gotoSlider() 함수 바깥에선 쓸 수 없습니다.

지역 변수로 선언하지 않았기 때문에 한 번 더 선언을 해야 합니다.

여기선 변수 dotClick에 모든 dot을 할당하고, 요소에 addEventListener()를 이용해 클릭했을 때 실행할 기능을 설정합니다.

여기서 우리는 dot의 index가 슬라이더의 index와 동일하게 작용한다는 점을 이용하면 편리하게 코드를 재활용할 수 있습니다.

gotoSlider() 함수가 매개변수로 각 index를 받고 있고, 여기서 클릭하는 dot의 index는 몇 번째 dot을 클릭했는지를 의미하므로 그대로 매개변수로 사용하면 됩니다.

 


 

👍 이번 예제 완성 화면 보러 가기

👍 이번 예제 코드 보러 가기

👍 다른 예제 살펴보기