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

Leeyanggoo

[JS] 자바스크립트 슬라이드 7 !! 썸네일 슬라이드 만들기 본문

2023/JavaScript

[JS] 자바스크립트 슬라이드 7 !! 썸네일 슬라이드 만들기

Leeyanggoo 2023. 4. 15. 15:15

 

 

 

 

 

 

#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 {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 800px;
    height: 450px;
    box-shadow: 0 50px 100px rgba(0,0,0,0.5);
}
.slider__img {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.slider__img img {
    position: absolute;
    width: 100%;
    height: 100%;
    /* background-size: cover; */
    object-fit: cover;   /* img 태그로 불러왔을 때 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%, 150px);
    width: 100px;
    display: flex;
    justify-content: center;
    gap: 10px;
}
.slider__thumb img {
    cursor: pointer;
    border: 2px solid transparent; /* 보더도 위치값을 가지기 때문에 transparent(색상 투명하게) 씀 */
}
.slider__thumb img.active {
    border: 2px solid #fff;
}
.slider__btn a {
    display: flex;
    position: absolute;
    top: 0;
    width: 40px;
    height: 100%;
    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:hover {
    background-color: rgba(0,0,0,0.5);
}
.slider__btn a.next {
    right: 0;
}
.slider__btn a.prev {
    left: 0;
}

 

<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>    <!--title은 웹 접근성을 위함임-->
            <a href="#" class="next" title="다음 이미지">next</a>
        </div>
    </div>
</main>

 

이번 예제는 각각의 슬라이드가 버튼(prev)과 하단의 썸네일을 클릭했을 때 넘어가는 유형입니다.

전과 달리 이번에는 이미지를 스크립트를 이용해 추가하였으며, 썸네일을 클릭했을 때 opacity(투명도)를 할당해서 다음 슬라이드나 나타나는 모양으로 설정했습니다.

 

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

 

Javascript

// 이미지 불러오기
let images = [
    "./img/sliderEffect06-min.jpg",
    "./img/sliderEffect07-min.jpg",
    "./img/sliderEffect08-min.jpg",
    "./img/sliderEffect09-min.jpg",
    "./img/sliderEffect10-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;

    //썸네일 활성화(active)하기
    let thumnailNodes = slider.thumnails.querySelectorAll("img");
    thumnailNodes[currentIndex].classList.add("active");

    thumnailNodes.forEach((el, i) => {
        el.addEventListener("click", function(){
            slider.thumnails.querySelector("img.active").classList.remove("active");
            el.classList.add("active");

            imageNodes[currentIndex].classList.remove("active");
            currentIndex = i;
            imageNodes[currentIndex].classList.add("active");
        });
    });

    //왼쪽 버튼 클릭하기
    slider.prevBtn.addEventListener("click", ()=>{
        imageNodes[currentIndex].classList.remove("active");
        currentIndex--;

        //0에서 빼도 음수가 안 나오도록
        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", ()=>{
        imageNodes[currentIndex].classList.remove("active");

        //index가 최대 개수 안 넘게 하기(여기서 currentIndex에 +1을 하기 때문에 ++ 안 함)
        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);

 

먼저 불러올 이미지를 변수 images에 배열 속에 담았습니다.

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

이번 예제는 선택자를 변수 slider의 객체로 담고 있습니다.

이렇게 요소들을 배열 혹은 객체로 관리하는 이유는 추후의 유지 보수가 더욱 편리하다는 장점이 있기 때문입니다.

 

함수 imageSlider()의 매개변수 parent는 document.querySelector(".slider__wrap")를 할당받기 때문에 HTML 요소들의 가장 큰 부모 박스를 뜻합니다.

두 번째 매개변수 images는 앞서 슬라이드에 추가할 모든 이미지 배열을 가리킵니다.

따라서 변수 slider의 key가 선택자 변수명이 되며, 값은 HTML 요소들이 됩니다.

 

이미지 출력하고 활성화하기

slider.images는 innerHTML 속성을 사용하여 images 배열의 요소를 반복하면서 <img> 태그를 생성합니다.

생성된 <img> 태그들을 join() 메서드를 이용해 하나의 문자열로 결합합니다.

imageNodes는 모든 <img> 태그를 담고 있는 변수이므로 인덱스인 currentIndex를 붙여 현재 보여지는 이미지에 acitve 클래스를 추가합니다.

 

썸네일 이미지 출력하고 활성화하기

썸네일 이미지는 보여줄 슬라이드 이미지의 축소판이므로 크기를 CSS로 설정하고 앞서 이미지를 출력했던 것처럼 불러오고 활성화합니다.

thumnailNodes는 모든 썸네일 요소를 담고 있는 변수이므로 forEach문을 이용해 각각 요소에 클릭 이벤트를 추가하여, 썸네일을 클릭하면 해당 슬라이드로 넘어가는 실행문을 추가합니다.

먼저 모든 썸네일에 active 클래스를 제거한 뒤에 클릭한 요소에만 active 클래스를 추가합니다.

 

slider.thumnails.querySelector("img.active").classList.remove("active");
el.classList.add("active"); 

 

그뒤에 이미지 또한 같은 active 클래스가 제거되고, 클릭한 해당 인덱스의 이미지만 active 클래스를 추가하는 실행문을 적어줍니다.

currentIndex가 썸네일의 인덱스인 i를 할당받아서 슬라이드의 인덱스를 바꾼 뒤에 active를 추가합니다.

 

imageNodes[currentIndex].classList.remove("active");
currentIndex = i;
imageNodes[currentIndex].classList.add("active");

 

버튼 클릭 이벤트 만들기

좌우 버튼은 이전 이미지 혹은 다음 이미지를 불러오기 위해 사용하므로, currentIndex가 하나씩 줄어들거나 추가하는 코드를 작성해야 합니다.

또한 currentIndex가 모든 이미지 개수를 초과하지 않아야 하고, 음수가 나오면 안 되기 때문에 조건문이나 계산식을 작성해야 합니다.

 

왼쪽 버튼은 인덱스가 하나씩 줄어들어야 하므로 연산자 --를 이용했으며, 음수가 나오지 않게 하기 위해 0보다 작다면 currentIndex를 배열 인덱스에 맞게 하기 위해 총 개수에서 1을 뺀 값으로 변경하는 if 조건문을 사용했습니다.

오른쪽 버튼은 클릭 이벤트가 발생할 때마다 1을 더하고 총 개수를 나눈 나머지 값을 할당받습니다.

이렇게 되면 총 개수를 넘어서는 경우 0을 할당받기 때문에 첫 슬라이드로 이동하게 됩니다.

 


 

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

👍 이번 예제 코드 보러 가기

👍 다른 예제 살펴보기