Javascript - 슬라이드 구현 종합 (버튼,무한,자동,드래그,멈춤)

컴퓨터/Javascript

728x90
반응형

서론

캐러셀(Carousel) 또는 슬라이더(Slider)등으로 불리고 있는 다양한 웹 서비스에서 볼 수 있는 콘텐츠이다.

본문에서는 "캐러셀"보다는 "슬라이드"라는 표현을 많이 사용하도록 하겠습니다.

 

웹 콘텐츠로 제공되는 이 슬라이드기능은 서비스 제공자에 의도에 따라 다양한 기능들이 존재합니다.

  • 페이지네이션이 존재하는 슬라이더
  • 좌측 우측 버튼이 존재하는 슬라이더
  • 스와이프(드래그)로 움직이는 슬라이더
  • 마지막 페이지가 끝나면 첫 번째 페이지로 이동하는 슬라이더
  • 자동으로 무한 반복되는 슬라이더
  • 자동으로 반복되지만, 마우스 커서가 올라오면 멈추는 슬라이더

이런 기능들이 있으며, 추가로 다양한 애니메이션 효과를 집어넣을 수 있습니다.

본문에서는 직접 순수 Javascript를 이용해 기능들을 구현해 보도록 하겠습니다.

 

주의!

공부목적이라면 해당 글을 읽으면 도움이 될 수 있습니다.

하지만 당장 페이지 슬라이더를 사용하고 싶다면 라이브러리를 사용하는 것을 적극 권장합니다.

수십 개의 해당 기능을 구현한 라이브러리를 이 존재합니다.

 

준비를 위한 기본 소스코드

우선 flex를 이용해 슬라이드할 아이템을 넣은 화면을 만들어 보도록 합시다.

See the Pen Slide - Step1(Form) by Gon (@gon-91) on CodePen.

이 소스코드를 베이스로 두고, 하나씩 기능을 구현해 보도록 하겠습니다.

페이지네이션 슬라이더

See the Pen Slide - Step1(Form) by Gon (@gon-91) on CodePen.

위의 화면을 만들기 위해 HTML,CSS,JS를 모두 JS를 통해 만들어 보도록 합시다.

해당 소스코드 주석만 읽고, 충분히 이해가 되면, 다음 챕터를 이용하시면 됩니다.

  • 슬라이드 이동 구현
//슬라이드 이동 함수
function goToSlide(index){
    currentSlide = index;
    slideContainer[0].style.transition = 'transform 0.5s ease';
    slideContainer[0].style.transform = `translateX(-${slideWidth * currentSlide}px)`;
}

우선 특정 번호를 인자로 받는 슬라이드 이동함수를 만들어 줍니다. 그리고 슬라이드를 감싸고 있는 컨테이너 함수에 애니메이션 효과를 부여합니다.

  • CSS 삽입을 위한 함수 구현
//CSS 삽입 함수
function AddStyle(style){
    const styleTag = document.createElement('style');
    styleTag.innerHTML = style;
    document.head.appendChild(styleTag);
}

특정 문자열을 받아 해당 HTML에 CSS 스타일을 삽입하는 함수를 만들어 줍니다.

  • 페이지 네이션 HTML,CSS 생성 삽입, 슬라이드 이동 이벤트 생성
// 페이지네이션 생성
function Createpagination(){
    //HTML Tag 생성
    slidewrap.innerHTML += `<div class="pagination"></div>`;
    const pagination = document.querySelector(".pagination");
    for (let i = 1 ; i < slidescnt; i++){
        if(i===1){pagination.innerHTML += `<li class="act"><a>•</a></li>`;}
        pagination.innerHTML += `<li><a>•</a></li>`;
    }

    //CSS 생성
    const paginationStyle = `
        .pagination {
            display : flex;
            position : absolute;
            left : 50%;
            transform: translateX(-50%);
            bottom : 0;
        }
        .pagination li{
            font-size : 50px;
            list-style: none;
            color:  white;
            opacity: 0.5;
        }
        .pagination .act{
            opacity: 1;
        }
    `
    AddStyle(paginationStyle);

    //페이지네이션 이벤트 생성
    const paginationlink = document.querySelectorAll(".pagination li a");
    paginationlink.forEach((link, index) => {
        link.addEventListener('click', (event) => {
          event.preventDefault(); // 기본 앵커 링크 동작을 막습니다.
          goToSlide(index);
        });
    });
}

페이지네이션 HTML 및 CSS를 생성, 삽입하고 생성된 태그에 이벤트로 슬라이드 이동을 추가합니다.

  • 슬라이드 이동시 페이지네이션 상태 변경
//슬라이드 이동 함수
function goToSlide(index){
    currentSlide = index;
    slideContainer[0].style.transition = 'transform 0.5s ease';
    slideContainer[0].style.transform = `translateX(-${slideWidth * currentSlide}px)`;
	// 추가 부분
    //페이지네이션 Class 부여하기  
    const pagination = document.querySelectorAll(".pagination li");
    for (let i = 0 ; i < pagination.length ; i++){
        if(i === index){
            pagination[i].classList.add("act");
            continue;
        }
        pagination[i].classList.remove("act");
    }
}

페이지네이션의 상태 마크가 페이지에 따라 변경될 수 있도록 클래스 속성을 제어해 줍니다.

 

버튼 슬라이더

See the Pen Slide - Step2(button) by Gon (@gon-91) on CodePen.

페이지네이션과 아주 유사합니다.

단 좌우에 2개의 버튼으로 다음 슬라이드로 이동하기 때문에 3항 연산자를 이용하여 슬라이드 이동을 제한하였습니다.

    //버튼 이벤트 생성
    const BtnL = document.querySelector(".leftbtn");
    BtnL.addEventListener('click',(event)=>{
        event.preventDefault(); // 기본 앵커 링크 동작을 막습니다.
        const index = (currentSlide-1) >=0 ? currentSlide-1 : 0; // 삼항 연산을 통해 페이지 이동 최소 값 제한
        goToSlide(index);
    })
    const BtnR = document.querySelector(".rightbtn");
    BtnR.addEventListener('click',(event)=>{
        event.preventDefault(); // 기본 앵커 링크 동작을 막습니다.
        const index = (currentSlide+1) < slidescnt ? currentSlide+1 : slidescnt-1; //삼항 연산을 통해 페이지 이동 최대 값 제한
        goToSlide(index);
    })

루프 슬라이더

See the Pen Slide - Step2(button) by Gon (@gon-91) on CodePen.

 

좌우 버튼의 상한선 제한을 지우고, 계속해서 순환할 수 있도록 바꿔주었습니다.

    //버튼 이벤트 생성
    const BtnL = document.querySelector(".leftbtn");
    BtnL.addEventListener('click',(event)=>{
        event.preventDefault(); // 기본 앵커 링크 동작을 막습니다.
        const index = (currentSlide-1) >=0 ? currentSlide-1 : slidescnt-1; // 삼항 연산을 통해 페이지 이동 최소 값 제한
        goToSlide(index);
    })
    const BtnR = document.querySelector(".rightbtn");
    BtnR.addEventListener('click',(event)=>{
        event.preventDefault(); // 기본 앵커 링크 동작을 막습니다.
        const index = (currentSlide+1) < slidescnt ? currentSlide+1 : 0; //삼항 연산을 통해 페이지 이동 최대 값 제한
        goToSlide(index);
    })

스와이프  &  드래그 슬라이더

이제 화면을 드래그하거나 스마트폰 환경에서 스와이프를 하는 동작에 대한 이벤트를 추가해 봅시다.

See the Pen Slide - Step2(button+loop) by Gon (@gon-91) on CodePen.

위 2개와는 다르게 HTML이나 CSS의 삽입이 아닌 우리가 사용할 슬라이드 컨테이너에 4가지 이벤트를 부여해 줍니다.

  • 마우스 클릭 지점 때 이벤트
  • 마우스 클릭 해제 지점 때 이벤트
  • 터치 시작 때 이벤트
  • 터치 해제 때 이벤트

즉 시작과 종료일 때 위치를 기억하고 그에 따른 슬라이드 제어를 해주는 이벤트를 생성하면 됩니다.

    //마우스를 클릭 시작
    slideContainer[0].addEventListener("mousedown",(event)=>{
        startpos = event.pageX;
    })
    //마우스를 클릭 해제
    slideContainer[0].addEventListener("mouseup",(event)=>{
        endpos = event.pageX;

        //시작과 종료 지점의 포지션 값 비교 후 슬라이드 이동 실행 및 초기화
        if (startpos < endpos){
            const index = (currentSlide-1) >=0 ? currentSlide-1 : slidescnt-1; // 삼항 연산을 통해 페이지 이동 최소 값 제한
            goToSlide(index);
        }
        else{
            const index = (currentSlide+1) < slidescnt ? currentSlide+1 : 0; //삼항 연산을 통해 페이지 이동 최대 값 제한
            goToSlide(index);
        }
        //pos 값 초기화
        startpos = 0;
        endpos = 0;

    })
    //터치 시작
    slideContainer[0].addEventListener("touchstart",(event)=>{
        startpos = event.touches[0].pageX;
    })
    //터치 해제
    slideContainer[0].addEventListener("touchend",(event)=>{
        endpos = event.touches[0].pageX;

        //시작과 종료 지점의 포지션 값 비교 후 슬라이드 이동 실행 및 초기화
        if (startpos < endpos){
            const index = (currentSlide-1) >=0 ? currentSlide-1 : slidescnt-1; // 삼항 연산을 통해 페이지 이동 최소 값 제한
            goToSlide(index);
        }
        else{
            const index = (currentSlide+1) < slidescnt ? currentSlide+1 : 0; //삼항 연산을 통해 페이지 이동 최대 값 제한
            goToSlide(index);
        }
                //pos 값 초기화
                startpos = 0;
                endpos = 0;
    })

무한 루프 자동 슬라이더

특정 시간마다 자동으로 넘어가는 슬라이더를 구현해 봅시다.

See the Pen Slide - Step2(Drag) by Gon (@gon-91) on CodePen.

어떻게 보면 가장 간단한 방법입니다. 한 칸씩 슬라이드를 이동시키는 것을 일정 시간마다 반복하면 됩니다.

다음 슬라이드로 이동하기 위한 코드 구현을 하고, 해당 코드를 일정한 시간에 따라 호출하면 됩니다.

/*  무한 루프 자동 슬라이드 구현 (사실 next slide일 뿐)

*/
function autoslide(){
    const index = (currentSlide+1) < slidescnt ? currentSlide+1 : 0;
    goToSlide(index);
}

setInterval(autoslide,3000); //일정 시간마다 호출

커서 감지 슬라이더

See the Pen Slide - Step2(Drag) by Gon (@gon-91) on CodePen.

만약에, 위와 같이 자동으로 넘어가는 슬라이드를 구현했습니다.

사용자가 원하는 순간에는 멈출 수 있어야지만 그 슬라이드를 제대로 확인할 수 있습니다.

따라서 마우스가 올라간 시점은 사용자가 원하는 순간이라 생각하고 오토 슬라이드를 멈추는 기능을 추가하겠습니다.

 

여기서 중요한 부분은 일정 시간마다 함수를 호출하는 setInterval함수를 변수와 시키고 측정 조건에 따라 해제할 수 있도록 한 부분입니다.

/*  무한 루프 자동 슬라이드 구현 (사실 next slide일 뿐)

*/
let Autoslideactive = null ; // 슬라이드 자동 이동 호출을 변수 화
function autoslide(){
    const index = (currentSlide+1) < slidescnt ? currentSlide+1 : 0;
    goToSlide(index);
}
/*  마우스 감지 시 슬라이드 자동 멈추기

*/
function Createmousedetector(){
    //마우스가 슬라이드에 올라왔을 때
    slideContainer[0].addEventListener("mouseover",(event)=>{
        clearInterval(Autoslideactive);
    })
    //마우스가 슬라이드에서 나온 경우 다시 실행
    slideContainer[0].addEventListener("mouseout",(event)=>{
        Autoslideactive = setInterval(autoslide,3000);
    })
}
//웹 브라우저 시작
Autoslideactive = setInterval(autoslide,3000); //일정 시간마다 호출
Createmousedetector();

종합

마지막으로 모든 기능이 담긴 끔찍한 혼종을 보여드리며 글을 마치도록 하겠습니다.

사실 이 기능들을 만들면서 HTML과 CSS는 따로 제어한다고 가정하면 JS코드의 양은 생각보다 적고 알아야 될 기능 또한 엄청 적습니다. 

기본적인 문법을 안다는 가정하에 아래의 것들만 사용하면 문제없이 구현 가능할 것으로 예상됩니다.

  • document.querySelector
  • addEventListener
  • setInterval 및 변수화

See the Pen Slide - Step2(auto) by Gon (@gon-91) on CodePen.

 

728x90
반응형

Commnet

G91개발일지

Gon91(지구일)

91년생 공학엔지니어의 개발일지

TODAY :

YESTER DAY :

TOTAL :