๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Effect/Slide Effect

[Slide Effect] ์Šฌ๋ผ์ด๋“œ ์ดํŽ™ํŠธ 05 - ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ(๋ฒ„ํŠผ, ๋‹ท๋ฉ”๋‰ด)

by ์ฝ”๋”ฉ๊ณต์ฑ… 2022. 10. 14.
๋ฐ˜์‘ํ˜•

์Šฌ๋ผ์ด๋“œ ์ดํŽ™ํŠธ 05 : ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ(๋ฒ„ํŠผ, ๋‹ท๋ฉ”๋‰ด)

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ๊ทธ ๋™์•ˆ ๋ฐฐ์› ๋˜ JavaScript๋ฅผ ์ด์šฉํ•˜์—ฌ ์Šฌ๋ผ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์ง€๋‚œ๋ฒˆ ์Šฌ๋ผ์ด๋“œ04์—์„œ ๋„ฃ์—ˆ๋˜ ์—ฐ์†์ ์œผ๋กœ ์ขŒ์šฐ๋กœ ์›€์ง์ผ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๋ฒ„ํŠผ์—์„œ ๋‹ท๋ฉ”๋‰ด(Dot Menu)๋ฅผ ์ถ”๊ฐ€์‹œ์ผœ ๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


HTML ์†Œ์Šค

slider__wrap > slider__img > slider__inner ์•ˆ์— ์ด๋ฏธ์ง€ 5์žฅ์ด ๋“ค์–ด๊ฐ„ ๊ตฌ์กฐ์ด๋ฉฐ, ๊ทธ ์•„๋ž˜์˜ slider__btn divํƒœ๊ทธ ์•ˆ์— ์ด๋ฏธ์ง€๋ฅผ ์ขŒ์šฐ๋กœ ์Šฌ๋ผ์ด๋“œ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์„ ๋งŒ๋“ค์–ด๋‘์—ˆ๋‹ค. ๋งˆ์ง€๋ง‰ slider__dot์˜ ๊ฒฝ์šฐ ์•ˆ์˜ a ํƒœ๊ทธ๋“ค์„ JS๋กœ ์ถœ๋ ฅ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ฃผ์„ ์ฒ˜๋ฆฌํ•œ๋‹ค.

<body class="img08">
    <header id="header">
        <h1>JAVASCRIPT SLIDER EFFECT 05</h1>
        <p>์Šฌ๋ผ์ด๋“œ ์ดํŽ™ํŠธ โ‘ค - ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ(๋ฒ„ํŠผ, ๋‹ท๋ฉ”๋‰ด)</p>
        <ul>
            <li><a href="sliderEffect01.html">01</a></li>
            <li><a href="sliderEffect02.html">02</a></li>
            <li><a href="sliderEffect03.html">03</a></li>
            <li><a href="sliderEffect04.html">04</a></li>
            <li class="active"><a href="sliderEffect05.html">05</a></li>
            <li><a href="sliderEffect06.html">06</a></li>
            <li><a href="sliderEffect07.html">07</a></li>
        </ul>
    </header>
    <!-- // header -->

    <main id="main">
        <section id="sliderType01">
            <div class="slider__wrap">
                <div class="slider__img">
                    <div class="slider__inner">
                        <div class="slider"><img src="../assets/img/effect_bg10.jpg" alt="์ด๋ฏธ์ง€1"></div>
                        <div class="slider"><img src="../assets/img/effect_bg01.jpg" alt="์ด๋ฏธ์ง€2"></div>
                        <div class="slider"><img src="../assets/img/effect_bg03.jpg" alt="์ด๋ฏธ์ง€3"></div>
                        <div class="slider"><img src="../assets/img/effect_bg02.jpg" alt="์ด๋ฏธ์ง€4"></div>
                        <div class="slider"><img src="../assets/img/effect_bg04.jpg" alt="์ด๋ฏธ์ง€5"></div>
                    </div>
                </div>
                <div class="slider__btn">
                    <a href="#" class="prev">prev</a>
                    <a href="#" class="next">next</a>
                </div>
                <div class="slider__dot">
                    <!-- <a href="#" class="dot active">์ด๋ฏธ์ง€1</a>
                    <a href="#" class="dot">์ด๋ฏธ์ง€2</a>
                    <a href="#" class="dot">์ด๋ฏธ์ง€3</a>
                    <a href="#" class="dot">์ด๋ฏธ์ง€4</a>
                    <a href="#" class="dot">์ด๋ฏธ์ง€5</a> -->
                </div>
            </div>
        </section>
    </main>
    <!-- // main -->

    <footer id="footer"></footer>
    <!-- // footer -->
</body>

CSS ์†Œ์Šค

๊ธฐ์กด์˜ ์Šฌ๋ผ์ด๋“œ ํšจ๊ณผ์—์„œ ์“ฐ๋˜ CSS ์ฝ”๋“œ์— ๋‹ท ๋ฒ„ํŠผ(slider__dot) ์ฝ”๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค. ๊ณตํ†ต/์ดˆ๊ธฐํ™” ๋ถ€๋ถ„ CSS๋Š” ํ•˜๋‹จ์˜ CSS ์†Œ์Šค ๋ณด๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ํ™•์ธํ•  ๊ฒƒ.

/* slider */
.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 {    /*์ด๋ฏธ์ง€๋ฅผ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๋ถ€๋ชจ : ์›€์ง์ด๋Š” ๋ถ€๋ถ„*/
    display: flex;
    flex-wrap: wrap;
    width: 4800px;  /* ์ด ์ด๋ฏธ์ง€ 6๊ฐœ */
    height: 450px;
}
.slider {       /*๊ฐœ๋ณ„์ ์ธ ์ด๋ฏธ์ง€*/
    position: relative;
    width: 800px;
    height: 450px;
}
.slider::before {
    position: absolute;
    left: 5px;
    top: 5px;
    background: rgba(0,0,0,0.4);
    color: #fff;
    padding: 5px 10px;
}
.slider:nth-child(1)::before {content: '์ด๋ฏธ์ง€1';}
.slider:nth-child(2)::before {content: '์ด๋ฏธ์ง€2';}
.slider:nth-child(3)::before {content: '์ด๋ฏธ์ง€3';}
.slider:nth-child(4)::before {content: '์ด๋ฏธ์ง€4';}
.slider:nth-child(5)::before {content: '์ด๋ฏธ์ง€5';}
.slider:nth-child(6)::before {content: '์ด๋ฏธ์ง€1';}

@media (max-width: 800px) {
    .slider__img {
        width: 400px;
        height: 224px;
    }
}

/* ์Šฌ๋ผ์ด๋“œ ๋ฒ„ํŠผ */
.slider__btn a {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 50px;
    height: 50px;
    background: rgba(0,0,0,0.4);
    text-align: center;
    line-height: 50px;
    transition: all 0.2s ease;
    display: block;
    color: #fff;
}
.slider__btn a:hover {
    background: rgba(241,96,86,1);
    border-radius: 50px;
}
.slider__btn a.prev {
    left: 0;
}
.slider__btn a.next {
    right: 0;
}

.slider__dot {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 20px;
}
.slider__dot .dot {
    width: 20px;
    height: 20px;
    background: rgba(0,0,0,0.4);
    display: inline-block;
    border-radius: 50%;
    text-indent: -9999px;
    transition: all 0.3s;
    margin: 2px;
}
.slider__dot .dot.active {
    background: rgba(255,255,255,0.9);
}

JS ์†Œ์Šค

๋จผ์ € ์ƒ์ˆ˜์™€ ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑ ํ›„ ํ•„์š”ํ•œ ๋ถ€๋ถ„์„ ์ €์žฅํ•ด์ค€๋‹ค. ๊ทธ ๋‹ค์Œ ์ด๋ฏธ์ง€๋ฅผ ์›€์ง์ด๋Š” ์˜์—ญ์„ ๋งŒ๋“ค๊ณ  ๋งˆ์ง€๋ง‰์œผ๋กœ ์™ผ์ชฝ ๋ฒ„ํŠผ๊ณผ ์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ์˜ ๋™์ž‘์„ ์Šคํฌ๋ฆฝํŠธ๋กœ ๋งŒ๋“ ๋‹ค. ์ž์„ธํ•œ ์„ค๋ช…์€ ์ฃผ์„์„ ์ฐธ์กฐํ•  ๊ฒƒ.

const sliderWrap = document.querySelector(".slider__wrap");
const sliderImg = document.querySelector(".slider__img");       // ๋ณด์—ฌ์ง€๋Š” ์˜์—ญ
const sliderInner = document.querySelector(".slider__inner");   // ์›€์ง์ด๋Š” ์˜์—ญ
const slider = document.querySelectorAll(".slider");            // ๊ฐ๊ฐ์˜ ์ด๋ฏธ์ง€
const sliderDot = document.querySelector(".slider__dot");      // ์Šฌ๋ผ์ด๋” ๋‹ท

let currentIndex = 0;                       // ํ˜„์žฌ ์ด๋ฏธ์ง€
let sliderCount = slider.length;            // ์ด๋ฏธ์ง€ ๊ฐœ์ˆ˜
let sliderWidth = sliderImg.offsetWidth;    // ์ด๋ฏธ์ง€ ๊ฐ€๋กœ๊ฐ’
let dotIndex = "";

function init(){
    slider.forEach(() => dotIndex += "์ด๋ฏธ์ง€1");
    sliderDot.innerHTML = dotIndex;
    // ์ฒซ ๋ฒˆ์งธ ๋‹ท ๋ฒ„ํŠผํ•œํ…Œ ํ™œ์„ฑํ™” ํ‘œ์‹œ
    sliderDot.firstElementChild.classList.add("active");
}
init();

// ์ด๋ฏธ์ง€ ์ด๋™
function gotoSlider(num){
    sliderInner.style.transition = "all 400ms";
    sliderInner.style.transform = "translateX("+ -sliderWidth * num +"px)";
    currentIndex = num;

    // ๋‘๋ฒˆ์งธ ์ด๋ฏธ์ง€ ==> ๋‘๋ฒˆ์งธ ๋‹ท ํด๋ž˜์Šค ์ถ”๊ฐ€
    // 1. ๋‹ท ๋ฉ”๋‰ด ํด๋ž˜์Šค ๋ชจ๋‘ ์‚ญ์ œ
    // 2. ํ•ด๋‹น ์ด๋ฏธ์ง€ ํ•ด๋‹น ๋‹ท ๋ฉ”๋‰ด ํด๋ž˜์Šค ์ถ”๊ฐ€
    let dotActive = document.querySelectorAll(".slider__dot .dot");
    dotActive.forEach(el => el.classList.remove("active"));
    dotActive[num].classList.add("active");
}
    
// ๋ฒ„ํŠผ ํด๋ฆญํ–ˆ์„ ๋•Œ
document.querySelectorAll(".slider__btn a").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);
        }
    });
})

// ๋‹ท ๋ฒ„ํŠผ ํด๋ฆญํ–ˆ์„ ๋•Œ
document.querySelectorAll(".slider__dot .dot").forEach((dot, index) => {
    dot.addEventListener("click", () => {
        gotoSlider(index);
    });
});
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€


Reference Book

JavaScript
HTML
CSS
๊ด‘๊ณ  ์ค€๋น„์ค‘์ž…๋‹ˆ๋‹ค.