이펙트 효과/슬라이드 이펙트

JS 슬라이드 이펙트 적용해보기! - 6 닷 버튼 클릭

우당당쿵당콩탕 2023. 4. 13. 18:52
728x90
반응형

 

슬라이드 이펙트 여섯번 째!

버튼으로 이동하는 슬라이드와 닷 버튼을 눌렀을 때 해당 이미지로 이동하는 슬라이드 이펙트입니다.

CSS

 <style>
   /* slider__wrap */
   .slider__wrap {
     width: 100%;
     height: 100vh;
     display: flex;
     align-items: center;
     justify-content: center;
   }
   .slider__img {
    /* 이미지가 보이는 영역이기 때문에 와이드 값을 이미지만큼 설정 */
    position: relative;
    width: 800px;
    height: 450px;
    overflow: hidden;
   }
   .slider__inner {
    /* 전체 이미지를 감싸고 있는 부모 : 움직이는 영역 / 이미지의 사이즈가 450이고 다섯장이기 때문에 2250*/
    display: flex;
    flex-wrap: wrap;
    width: 4800px; 
    height: 450px;
   }
   .slider {
    position: relative;
    width: 800px;
    height: 450px;
    /* 개별적인 이미지 */
   }
   .slider__btn a {
        position: absolute;
        top: 50%;
        transform: translateY(-50%);
        width: 50px;
        height: 50px;
        background-color: #fff;
        line-height: 50px;
        text-align: center;
   }
   .slider__btn a:hover {
    background-color: rgb(0, 0, 0);
    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.3);
        display: inline-block;
        border-radius: 50%;
        text-indent: -9999px;
        transition: all 0.3s;
        margin: 3px;
   }
   .slider__dot .dot.active {
        background-color: #fff;
   }

닷 버튼 CSS를 추가했습니다. 닷과 버튼은 내비게이션 기능을 담당합니다.

Script

//선택자
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")        //버튼

 

선택자(변수)를 먼저 살펴보겠습니다.

 

  • sliderWrap: 슬라이더를 감싸고 있는 전체를 말합니다.
  • sliderImg: 슬라이더 이미지가 보여지는 영역을 나타냅니다.
  • sliderInner: 슬라이더 이미지가 움직이는 영역을 나타냅니다.
  • slider: 슬라이더 이미지들을 나타냅니다.
  • sliderDot: 슬라이더 하단에 위치한 닷 메뉴를 나타냅니다. (네비게이션역할)
  • sliderBtn: 슬라이더 좌우에 위치한 이전/다음 버튼입니다.
let currentIndex = 0;                                   //현재 보이는 이미지.
let sliderCount = slider.length;                        //이미지 전체 개수.
let sliderWidth = slider[0].offsetWidth;                //이미지 가로값
let sliderInterval = 2000;
let dotIndex = "";
  • currentIndex: 현재 보여지는 이미지를 나타내는 변수입니다. gotoslider라는 함수 내에서 이미지를 이동 시키면 이 변수에 할당하고, 이미지를 업데이트(보여지는 이미지)를 합니다.
  • sliderCount: 이미지의 전체 개수를 저장합니다.
  • sliderWidth: 이미지의 가로 길이를 저장합니다.
  • sliderInterval: 슬라이더가 자동으로 이동하는 간격을 저장합니다.
  • dotIndex: 슬라이더 닷 메뉴의 HTML 코드를 저장합니다.
function init(){
    //이미지 갯수만큼 닷 메뉴 생성
    slider.forEach(() => dotIndex += "<a href='#'' class='dot'>이미지2</a>");
    sliderDot.innerHTML = dotIndex;

    //첫 번째 닷 메뉴한테 활성화 표시하기
    sliderDot.firstChild.classList.add("active");

    // 닷버튼 클릭
    const dotClick = sliderWrap.querySelectorAll(".slider__dot .dot")
    dotClick.forEach((el, index) => {
        el.addEventListener("click", () => {
            gotoSlider(index);
        });
    });
}
init();

이미지의 개수만큼 닷 메뉴를 생성하기 위해 forEach를 사용합니다. 이 반복문으로 slider라는 변수에 저장된 이미지 요소들의 개수만큼 반복문이 실행되고, 실행될때마다 dotindex에 문자열이 추가됩니다. 

init()

sliderWrap에서 선택한 요소를 초기화 하고, 슬라이더 닷 메뉴를 생성함과 동시에 첫 번째 이미지의 닷 메뉴를 활성화(active)합니다.

추가로 이벤트를 추가해 클릭시에 gotoSlider함수를 호출합니다. 즉 클릭한 닷 메뉴와 매칭되는 슬라이더 이미지로 이동하게끔 구현되었습니다.

 

gotoSlider부분 Script

//이미지 이동시키기 => 해당 이미지로 찾아갈 수 있게끔.
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.forEach((active) => active.classList.remove("active"));
    dotActive[num].classList.add("active");
}

이 부분은 매칭된 이미지로 찾아 갈 수 있도록 하는 함수입니다. 여기서 num은 이미지 번호를 의미하고 이 번호는 currentIndex에 저장됩니다. 이동한 이미지에 해당하는 닷 메뉴를 활성하기 위해 먼저 remove를 통해 active클래스를 전체적으로 제거해주고, 이동한 이미지에 해당하는 닷 메뉴에 active클래스를 추가해줍니다. dot이 여러개 이기 때문에 querySelectorAll을 사용해주어야합니다.

sliderInner.style.transition = "all 400ms";
sliderInner.style.transform = "translateX("+ -sliderWidth * num +"px)";

sliderInne에 style 속성에 transform 애니메이션 효과를 주는 부분입니다.

두번 째 줄의 경우 translateX() 함수를 사용하여, sliderWidth 변수의 값을 이용하여 현재 인덱스 값에 해당하는 위치로 이동시킵니다. 음수 값을 곱해주는 이유는, translateX() 함수가 음수 값일 때는 왼쪽으로 이동시키고, 양수 값일 때는 오른쪽으로 이동시키기 때문입니다.

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

        if(btn.classList.contains("prev")){
            gotoSlider(prevIndex);
        } else {
            gotoSlider(nextIndex);
        }
    });
});

이 부분은 슬라이더 버튼을 클릭했을 때 이전 이미지 또는 다음 이미지를 보여주기 위한 함수입니다.

sliderBtn.즉 버튼들에 forEach를 사용하여 각각 click이라는 이벤트를 추가해줍니다. 

이전 이미지를 보여주는 버튼(prev)을 클릭하면, currentIndex로부터 이전 이미지의 인덱스를 구해 gotoSlider() 함수에 전달합니다. 구하는 방법은, sliderCount는 이미지의 총 갯수를 나타내는 변수이며, 이전 이미지의 인덱스는 (currentIndex + (sliderCount-1)) % sliderCount 입니다. 여기서 %는 나머지 연산자로, 총 이미지 수에 대해 나눈 나머지를 구하는 연산입니다.

반면, 다음 이미지를 보여주는 버튼(next)을 클릭하면, 이번에는 다음 이미지의 인덱스를 구하여 gotoSlider() 함수에 전달합니다. 구하는 방법은 (currentIndex + 1) % sliderCount 입니다.