사이트 제작

슬라이더 이펙트 사이트 만들기 07

진블로그 2023. 4. 14. 16:30
다른 명언

728x90
반응형

이번 시간은 슬라이드 버튼을 이미지 내부에 보이도록 하고, 닷 버튼 대신 썸네일 이미지를 추가하였습니다.

 

<!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%, 140px);
            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>
<body class="img09 bg08 font02">
    <header id="header">
        <h1>Javascript Slider Effect07</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>
    <!-- //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:ebmdols@naver.com">ebmdols@naver.com</a>
    </footer>
    <!-- //footer -->

</body>
</html>

object-fit

object-fit 속성은 이미지나 비디오와 같은 대체 콘텐츠를 표시할 때, 해당 콘텐츠를 포함하는 요소의 크기에 맞게 조정하거나 자르는 방법을 제어하는 데 사용됩니다. 이 속성은 CSS의 background-size 속성과 유사한 역할을 합니다.

fill: 대체 콘텐츠를 요소의 크기에 맞게 늘리거나 축소합니다. 가로세로 비율이 유지되지 않으며, 콘텐츠가 찌그러질 수 있습니다.
contain: 대체 콘텐츠가 요소의 크기 내에 완전히 들어가도록 늘립니다. 콘텐츠의 원래 가로세로 비율이 유지됩니다.
cover: 대체 콘텐츠가 요소의 크기를 완전히 덮도록 늘립니다. 콘텐츠의 원래 가로세로 비율이 유지됩니다.
none: 대체 콘텐츠를 요소의 크기에 맞게 조정하지 않습니다. 대신, 콘텐츠의 원래 크기를 유지합니다.
scale-down: none과 contain 중 적용할 수 있는 가장 작은 값을 사용합니다. 대체 콘텐츠가 요소의 크기를 초과하지 않도록 늘립니다.

 

opacity는 CSS 속성 중 하나로, 해당 요소의 투명도를 조절하는 데 사용됩니다. opacity 값은 0과 1 사이의 실수 값으로 지정할 수 있으며, 0은 요소가 완전히 투명하다는 것을 의미하고, 1은 요소가 완전히 불투명하다는 것을 의미합니다.

transparent는 CSS 색상 값 중 하나로, 투명한 색상을 나타내는 키워드입니다.

ease-in-out은 CSS 애니메이션 타이밍 함수 중 하나로, 처음과 끝 부분에서는 느리게 시작하고 끝나며, 중간 부분에서는 빠르게 진행되는 이징(easing) 함수입니다. 이징 함수는 CSS 애니메이션에서 애니메이션의 속도를 제어하는 데 사용됩니다.

 

<script>
    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");

        //썸네일 이미지 클릭하기
        // for(let i=0; i<thumna]ilNodes.length; i++){
        //     thumnailNodes[i].addEventListener("click", 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");
        //     });

        // }

        //썸네일 이미지 클릭하기
        thumnailNodes.forEach(function(el, index){
            el.addEventListener("click", function(){       
                slider.thumnails.querySelector("img.active").classList.remove("active")
                el.classList.add("active")

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


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

            //0 4 3 2 1 0 4 3 ...
            if(currentIndex < 0) currentIndex = images.length - 1;

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

            //썸네일
            thumnailNodes[currentIndex].classList.add("active");
        });

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


            //1 2 3 4 0 1 2 3...
            currentIndex = (currentIndex + 1) % images.length
            imageNodes[currentIndex].classList.add("active")

            //썸네일
            thumnailNodes[currentIndex].classList.add("active");
        })
    }
    imageSlider(document.querySelector(".slider__wrap"), images);

</script>

 

변수 images에 이미지들을 배열로 저장합니다.

함수 imageSlider에 매개변수 parent와 images를 넣어줍니다.

그 안에 선택자를 객체로 저장하여 줍니다.

이미지들과 썸네일 이미지, 이전 버튼, 다음 버튼을 위한 선택자를 만들었습니다.

 

이미지를 출력하기 위해 배열로 저장되어 있는 images를 map() 메서드를 사용하여 불러줍니다.

return `<img src="${image}" alt="이미지${index}">` 이미지 태그의 이미지 주소에는 slider.images.innerHTML 가 순서대로 반복적으로 들어가고 alt에는 map()메서드의 키 값 index가 차례로 들어갑니다.

 

let imageNodes = slider.images.querySelectorAll("img"); 코드는 slider 객체의 images 프로퍼티에서 img 요소를 모두 선택하여 imageNodes 변수에 할당합니다.

다음으로, imageNodes[currentIndex].classList.add("active") 코드는 imageNodes 변수에서 현재 인덱스(currentIndex)에 해당하는 img 요소에 active 클래스를 추가합니다. 이를 통해 현재 이미지를 활성화합니다.

그리고, slider.thumnails.innerHTML = slider.images.innerHTML; 코드는 slider 객체의 images 프로퍼티에 있는 이미지들을 slider 객체의 thumnails 프로퍼티에 있는 요소에 복사하여 출력합니다. 이를 통해 이미지와 동일한 순서의 썸네일을 생성합니다.

마지막으로, let thumnailNodes = slider.thumnails.querySelectorAll("img"); 코드는 slider 객체의 thumnails 프로퍼티에서 img 요소를 모두 선택하여 thumnailNodes 변수에 할당합니다.

thumnailNodes[currentIndex].classList.add("active"); 코드는 thumnailNodes 변수에서 현재 인덱스(currentIndex)에 해당하는 img 요소에 active 클래스를 추가합니다. 이를 통해 현재 썸네일을 활성화합니다.

 

slider.thumnails.innerHTML = slider.images.innerHTML; 코드는 slider 객체의 images 프로퍼티에 있는 이미지들을 slider 객체의 thumnails 프로퍼티에 있는 요소에 복사하여 출력합니다. 이를 통해 이미지와 동일한 순서의 썸네일을 생성합니다.

 

//왼쪽 버튼 클릭하기

if(currentIndex < 0) currentIndex = images.length - 1; 코드는 currentIndex 변수가 0보다 작아지면 images.length - 1로 설정하여 마지막 이미지로 이동합니다.

imageNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 이미지(imageNodes[currentIndex])에 active 클래스를 추가합니다.

thumnailNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 썸네일 이미지(thumnailNodes[currentIndex])에 active 클래스를 추가합니다.

 

//오른쪽 버튼 클릭하기

(currentIndex + 1) % images.length 코드는 currentIndex 변수에 1을 더한 뒤 images.length로 나눈 나머지 값을 반환하여, 이미지 배열을 순환하며 슬라이더를 동작시킵니다.

imageNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 이미지(imageNodes[currentIndex])에 active 클래스를 추가합니다.

thumnailNodes[currentIndex].classList.add("active") 코드는 업데이트된 currentIndex에 해당하는 썸네일 이미지(thumnailNodes[currentIndex])에 active 클래스를 추가합니다.

728x90