My Melody Kawaii

JAVASCRIPT/슬라이드 이펙트

슬라이드이펙트 07 - 버튼과 썸네일을 만들어서 움직여보자!

younajeong 2023. 4. 15. 16:08

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

슬라이드이펙트 07 - 버튼과 썸네일 만들어보기

 

슬라이드 이펙트 저번 시간에 이어서 버튼과 썸네일을 만들어서 움직일 수 있는 슬라이드 이펙트를 만들어 보았습니다.

버튼과 썸네일을 누를때마다 변하는 슬라이드 효과를 만들었습니다!

 

<완성본>

 

HTML & CSS

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>07. 슬라이드 이펙트</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/slider.css">
    <style>
        /* slider__wrap */
        .slider__wrap {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
            width: 800px;
            height: 450px;
            box-shadow: 0 50px 100px rgba(0,0,0,0.4);
        }
        .slider__img {
            position: relative;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }
        .slider__img img {
            position: absolute;
            width: 100%;
            height: 100%;
            object-fit: cover;
            opacity: 0;
            transform: scale(1.1);
            transition: all 500ms ease-in-out;
        }
        .slider__img img.active {
            opacity: 1;
            transform: scale(1);
        }
        .slider__thumb {
            position: absolute;
            left: 50%;
            top: 50%;
            transform: translate(-50%, 200%);
            width: 100px;
            display: flex;
            justify-content: center;
            gap: 10px;
        }
        .slider__thumb img {
            cursor: pointer;
            border:  2px solid transparent;
        }
        .slider__thumb img.active {
            border: 2px solid #fff;
        }
        .slider__btn a{
            position: absolute;
            top: 0;
            width: 40px;
            height: 100%;
            display: flex;
            justify-content: center;
            align-items: center;
            font-size: 12px;
            color: #fff;
            background-color: rgba(0,0,0,0.2);
            transition:  all 300ms ease-in-out;
        }
        .slider__btn a.next {
            right: 0;
        }
        .slider__btn a:hover {
            background-color: rgba(0,0,0,0.5);
        }

        
    </style>
</head>

    <!-- //header -->
<body class="img07 bg07 font07">
    <header id="header">
    <h1>Javascript sliderEffect07</h1>
    <p>슬라이드 이펙트 : 썸네일 슬라이드(버튼, 썸네일)</p>
    <ul>
        <li><a href="sliderEffect01.html">1</a></li>
        <li><a href="sliderEffect02.html">2</a></li>
        <li><a href="sliderEffect03.html">3</a></li>
        <li><a href="sliderEffect04.html">4</a></li>
        <li><a href="sliderEffect05.html">5</a></li>
        <li><a href="sliderEffect06.html">6</a></li>
        <li class="active"><a href="sliderEffect07.html">7</a></li>
    </ul>
    </header>

    <main id="main">
        <div class="slider__wrap">
            <div class="slider__img"></div>
            <div class="slider__thumb"></div>
            <div class="slider__btn">
                <a href="#" class="prev" title="이전이미지">prev</a>
                <a href="#" class="next" title="다음이미지">next</a>
            </div>
        </div>
    </main>
    <!-- //main -->

    <footer id="footer">
        <a href="mailto:jeongyouna_@naver.com">jeongyouna_@naver.com</a>
    </footer>  
    <!-- //footer -->

HTML&CSS

HTML의 구조에서는 전체 main안ㅇ세 slider__wrap을 만들어 준 후 그 안에 img 와 thumb를 만들어 줍니다. 그리고 btn을 만들어서 그 안에 넘어갈 수 있는 버튼이 생길 수 있도록 이전버튼 prev와 다음버튼 next를 만들어 준 후 footer에 이메일을 적어 줍니다.

 

CSS에서는 전체적으로 wrap에게 필요한 속성을 부여한 후 썸네일이 선택되면 생길 수 있는 효과를 부여해 줍니다. btn또한 전체적으로 flex를 부여해서 나란히 위치하게 한 후 그림자 효과를 주어서 클릭하면 색이 변할 수 있는 효과를 부여해 주었습니다.

 

 

 

 

Script

<script>
    
    let images = [
        "./img/sliderEffect03-min.jpg",
        "./img/sliderEffect04-min.jpg",
        "./img/sliderEffect05-min.jpg",
        "./img/sliderEffect06-min.jpg",
        "./img/sliderEffect07-min.jpg"
    ];

    function imageSlider(parent, images){
        let currentIndex = 0;    

        //선택자 : 함수안에 객체를 넣어준 유형
        let slider = {
            parent: parent,
            images: parent.querySelector(".slider__img"),
            thumnails:parent.querySelector(".slider__thumb"),
            prevBtn:parent.querySelector(".slider__btn .prev"),
            nextBtn:parent.querySelector(".slider__btn .next")
        }

        //이미지 출력하기
        slider.images.innerHTML = images.map((image, index) => {
            return `<img src="${image}" alt="이미지${index}">`;
        }).join("");

        //이미지 활성화(active)하기
        let imageNodes = slider.images.querySelectorAll("img");
        imageNodes[currentIndex].classList.add("active");

        //썸네일 이미지 출력하기 
        slider.thumnails.innerHTML = slider.images.innerHTML;

        //썸네일 첫번째 이미지 엑티브 추가
        // slider.thumnails.firstChild.classList.add("active");        //배열을 쓰면 All을 써야하는데 부모요소로 선택자를 줘서 자식요소를 선택해야 하기 때문에
    
        //썸네일 활성화(active)하기
        let thumnailNodes = slider.thumnails.querySelectorAll("img"); 
        thumnailNodes[currentIndex].classList.add("active");

         //썸네일 이미지 클릭하기
        // for (let i=0; i<thumnailNodes.length; i++){
        //     thumnailNodes[i].addEventListener("click", function(){      //function을 쓰면 this를 사용해서 위치값을 가져올 수 있다. 화살표 함수는 가져올 수 없음
        //         slider.thumnails.querySelector("img.active").classList.remove("active");
        //         thumnailNodes[i].classList.add("active");

        //         imageNodes[currentIndex].classList.remove("active");
        //         currentIndex = i;
        //         imageNodes[currentIndex].classList.add("active");
        //     });
        //     console.log(thumnailNodes[i])
        // }
        //forEach
        thumnailNodes.forEach((el,i) => {
            el.addEventListener("click", function(){      
                slider.thumnails.querySelector("img.active").classList.remove("active");
                thumnailNodes[i].classList.add("active");

                imageNodes[currentIndex].classList.remove("active");
                currentIndex = i;
                imageNodes[currentIndex].classList.add("active");
            });
        });
        //왼쪽 버튼 클릭하기
        slider.prevBtn.addEventListener("click", function(){
            imageNodes[currentIndex].classList.remove("active")
            currentIndex--;
            
            //0 4 3 2 1 0 4 3 2 1...
            if(currentIndex <0) currentIndex = images.length -1;   
            imageNodes[currentIndex].classList.add("active")

            //썸네일
            slider.thumnails.querySelector("img.active").classList.remove("active");
            thumnailNodes[currentIndex].classList.add("active");
        });

        //오른쪽 버튼 클릭하기
        slider.nextBtn.addEventListener("click", function(){
            imageNodes[currentIndex].classList.remove("active")
            // currentIndex++;

            //1 2 3 4 0 1 2 3 4...
            currentIndex = (currentIndex + 1) % images.length;

            imageNodes[currentIndex].classList.add("active")

            //썸네일
            slider.thumnails.querySelector("img.active").classList.remove("active");    //썸네일 선택자 만들기
            thumnailNodes[currentIndex].classList.add("active");
        });

    }


    imageSlider(document.querySelector(".slider__wrap"), images);

    </script>

script

  • 'images'은 배열을 사용해서 슬라이더에 사용될 이미지 파일의 경로로 저장해 줍니다.
  • imageSlider 함수는 parent와 images를 매개변수로 받아서, parent객체를 통해 슬라이더를 구현하는 함수입니다.
  • 이미지를 출력할 때는 HTML문자열 innerHTML을 사용해서 images의 div 내부에 삼입할 수 있도록 합니다.
  • 슬라이더의 초기 상태를 설정해서 현지 이미지의 인덱스를 '0'으로 초기화 한 다음에 images와 thumbnails요소 내부의 첫번째 자식 요소를 active시켜 줍니다.
  • 이미지를 클릭 이벤트를 사용하기 때문에 여러장 이미지가 있으므로 forEach매서를 사용해서 thumbnails 내부의 모든 이미지 요소에 클릭 이벤트를 사용합니다. 클릭 이벤트가 발생하면 현재 이미지와 썸네일 이미지를 비활성화 하고 클릭된 이미지를 활성화 시켜줍니다.
  • 좌우 화살표 버튼 클릭 이벤트도 각각 등록하여서 왼쪽 버튼을  클릭하면 현재 활성화 된 이미지와 썸네일을 비활성화 시키고 이전이미지를 활성화 오른쪽 버튼을 누르면 다음 이미지를 활성화 시켜줍니다.
  • 마지막으로 imageSlider함수를 호출하여, 슬라이더를 구현시켜줍니다.
  • document.querySelector메서드를 이요하여 slider__wrap클래스를 가진 요소를 선택하고, images배열을 전달시켜줍니다.