๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
EFFECT

[EFFECT]์Šฌ๋ผ์ด๋“œ ํšจ๊ณผ - ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ(๋ฒ„ํŠผ, dot๋ฉ”๋‰ด, ๋ฌดํ•œ)

by _ํ† ๋งคํ†  2022. 10. 24.
728x90

์Šฌ๋ผ์ด๋“œ ์ดํŽ™ํŠธ - ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ(๋ฒ„ํŠผ, dot๋ฉ”๋‰ด, ๋ฌดํ•œ์œผ๋กœ ์›€์ง์ด๊ธฐ)

์ด๋ฒˆ ์‹œ๊ฐ„์—๋Š” ์ด๋ฏธ์ง€๊ฐ€ ๋Š๊ธฐ์ง€ ์•Š๊ณ  ๊ณ„์† ์ด์–ด์ ธ์„œ ๋‚˜์˜ค๋Š” ๋ฌดํ•œ ์Šฌ๋ผ์ด๋“œ์™€ ๋‹ท๋ฉ”๋‰ด ๋ฒ„ํŠผ์œผ๋กœ ์›€์ง์ด๋Š” ์Šฌ๋ผ์ด๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค! ๐Ÿฅน


#1. HTML / CSS ์„ค์ •ํ•˜๊ธฐ

! HTML TIP !
๊ฐ ์ด๋ฏธ์ง€๋งˆ๋‹ค css์„ค์ •์„ ์ฃผ๊ธฐ ์œ„ํ•ด ๋”ฐ๋กœ ๋ถ€๋ชจ๋ฅผ 2๋ฒˆ ๊ฐ์‹ธ์„œ ๋ฌถ์–ด์ค๋‹ˆ๋‹ค.
๋˜ํ•œ ๋ฒ„ํŠผ ์•„๋ž˜ ๋‹ท๋ฉ”๋‰ด ๊ตฌ์กฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค. ๋‹ท ๋ฉ”๋‰ด๋Š” ์Šคํฌ๋ฆฝํŠธ๋กœ ๊ตฌํ˜„ํ•  ๊ฒƒ์ด๋ฏ€๋กœ ์ฃผ์„์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ค๋‹ˆ๋‹ค.

โœ๏ธ HTML ์Šคํฌ๋ฆฝํŠธ ๋ณด๊ธฐ
<main id="main">
    <section id="sliderType04">
        <div class="slider__wrap">
            <div class="slider__img">
                <div class="slider__inner">
                    <div class="slider s1" role="group" aria-label="1/5">
                        <span>์ด๋ฏธ์ง€1</span>
                        <img src="../assets/img/Mountian_bg01.jpg" alt="์ด๋ฏธ์ง€6">
                    </div>
                    <div class="slider s2" role="group" aria-label="2/5">
                        <span>์ด๋ฏธ์ง€2</span>
                        <img src="../assets/img/Mountian_bg02.jpg" alt="์ด๋ฏธ์ง€7">
                    </div>
                    <div class="slider s3" role="group" aria-label="3/5">
                           <span>์ด๋ฏธ์ง€3</span>
                        <img src="../assets/img/Mountian_bg03.jpg" alt="์ด๋ฏธ์ง€8">
                    </div>
                    <div class="slider s4" role="group" aria-label="4/5">
                           <span>์ด๋ฏธ์ง€4</span>
                        <img src="../assets/img/Mountian_bg04.jpg" alt="์ด๋ฏธ์ง€9">
                    </div>
                    <div class="slider s5" role="group" aria-label="5/5">
                           <span>์ด๋ฏธ์ง€5</span>
                        <img src="../assets/img/Mountian_bg05.jpg" alt="์ด๋ฏธ์ง€10">
                    </div>
                </div>
            </div>

            <div class="slider__btn">
                <button href="#" class="prev" role="button" aria-label="์™ผ์ชฝ ์ด๋ฏธ์ง€">prev</button>
                <button href="#" class="next" role="button" aria-label="์˜ค๋ฅธ์ชฝ ์ด๋ฏธ์ง€">next</button>
            </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 -->

! CSS TIP !
1. ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€๋กœ๋กœ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํฌ์ง€์…˜์„ relative๋กœ ์„ค์ •ํ•˜๊ณ  ์˜์—ญ์—์„œ ๋ฒ—์–ด๋‚˜๋Š” ์ด๋ฏธ์ง€๋ฅผ ์•ˆ๋ณด์ด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด overflow: hidden์„ ์„ค์ •ํ•ด์ค๋‹ˆ๋‹ค.
2. ์ด๋ฏธ์ง€ ๊ฐ€๋กœ ๊ฐ’์€ ์ด๋ฏธ์ง€๊ฐ€ ์ž˜๋ฆฌ์ง€ ์•Š๋Š” ์„ ์—์„œ ์ตœ๋Œ€๋กœ ์„ค์ •ํ•ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. 3. pointer-events: none์„ ํ†ตํ•ด ๋ฒ„ํŠผ์ด ์—ฐ์†์œผ๋กœ ๋ˆŒ๋ฆฌ์ง€์•Š๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

โœ๏ธ 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: 10000px; /* ์Šคํฌ๋ฆฝํŠธ๋กœ ์ฒ˜๋ฆฌํ•  ๊ฒƒ์ด๋ฏ€๋กœ ์•ˆ๊นจ์ง€๊ฒŒ ๋” width๊ฐ’ ์ฃผ๋ฉด ๋จ */
    height: 450px;
    position: relative;
    left: -800px; /* ์Šฌ๋ผ์ด๋” ์ดˆ๊ธฐ๊ฐ’ */
}
/* ๋งˆ์ง€๋ง‰์—์„œ ์ฒ˜์Œ์œผ๋กœ ์ˆœ๊ฐ„์ด๋™ */
.slider__inner.transition {
    transition: all 0.3s;
}
.slider {   /* ๊ฐœ๋ณ„์ ์ธ ์ด๋ฏธ์ง€ (๊ฐ๊ฐ์˜ ์ด๋ฏธ์ง€ ์„ค์ •) */
    position: relative;
    width: 800px;
    height: 450px;
}
.slider span {
    position: absolute;
    left: 5px;
    top: 5px;
    background: rgba(0, 0, 0, 0.4);
    color: #fff;
    padding: 5px 10px;
}

@media(max-width : 800px){
    .slider__img {
        width: 400px;
        height: 250px;
    }
    .slider {
        width: 400px;
        height: 250px;
    }
}
/* ์Šฌ๋ผ์ด๋“œ ๋ฒ„ํŠผ ์—ฐ์†์œผ๋กœ ๋ˆ„๋ฅผ ์ˆ˜ ์—†๊ฒŒ ํ•˜๊ธฐ 01 */
.slider__btn.disable button{
        pointer-events: none;
    }

.slider__btn button {
    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;
    display: block;
    color: #fff;
    pointer-events: auto;
    border: 0;
    cursor: pointer;
}
.slider__btn button:hover {
    border-radius: 50px;
    background: rgba(38, 52, 103, 0.4);
}
.slider__btn button.prev {
    left: 0;
}
.slider__btn button.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: 3px;
}
.slider__dot .dot.active {
    background: rgba(255,255,255,0.9);
}

#2. JAVASCRIPT : ์Šคํฌ๋ฆฝํŠธ ์งœ๊ธฐ

cloneFirst = sliderFirst.cloneNode(true) / cloneLast = sliderLast.cloneNode(true)๋ฅผ ํ†ตํ•ด ์ฒซ๋ฒˆ์งธ ์ด๋ฏธ์ง€์™€ ๋งˆ์ง€๋ง‰ ์ด๋ฏธ์ง€๋ฅผ ๋ณต์‚ฌํ•ด์ค๋‹ˆ๋‹ค.
๋งค๊ฐœ๋ณ€์ˆ˜์™€ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜์—ฌ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋” ํšจ๊ณผ์ ์œผ๋กœ ์ž‘์„ฑํ•ด์ค๋‹ˆ๋‹ค.
๊ทธ ์™ธ ์„ธ๋ถ€์ ์ธ ๋ถ€๋ถ„์€ ์•„๋ž˜์˜ ์ฃผ์„๊ณผ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค!

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");              //๋‹ท ๋ฉ”๋‰ด
const sliderBtn = document.querySelector(".slider__btn");              //๋ฒ„ํŠผ
const sliderBtnPrev = document.querySelector(".slider__btn .prev");    //์™ผ์ชฝ ๋ฒ„ํŠผ
const sliderBtnNext = document.querySelector(".slider__btn .next");    //์˜ค๋ฅธ์ชฝ ๋ฒ„ํŠผ

let currentIndex = 0,                         //ํ˜„์žฌ ์ด๋ฏธ์ง€
    sliderLength = slider.length,             //์Šฌ๋ผ์ด๋” ์ด ๊ธธ์ด
    sliderWidth = slider[0].offsetWidth,      //์Šฌ๋ผ์ด๋” ๊ฐ€๋กœ ๊ฐ’
    sliderFirst = slider[0],                  //์ฒซ๋ฒˆ์งธ ์ด๋ฏธ์ง€
    sliderLast = slider[sliderLength -1],     //๋งˆ์ง€๋ง‰ ์ด๋ฏธ์ง€
    cloneFirst = sliderFirst.cloneNode(true), //์ฒซ๋ฒˆ์งธ ์ด๋ฏธ์ง€ ๋ณต์‚ฌ
    cloneLast = sliderLast.cloneNode(true);   //๋งˆ์ง€๋ง‰ ์ด๋ฏธ์ง€ ๋ณต์‚ฌ

sliderInner.appendChild(cloneFirst);
sliderInner.insertBefore(cloneLast, sliderFirst);

function init(){
    let dotIndex = "";
    //์ด๋ฏธ์ง€ ๊ฐฏ์ˆ˜๋งŒํผ ๋‹ท ๋ฉ”๋‰ด ์ƒ๊ธฐ๋„๋ก
    for(let i=0; i<sliderLength; i++){
        dotIndex += "<a href='#' class='dot'>์ด๋ฏธ์ง€1</a>"
        sliderDot.innerHTML = dotIndex;
        sliderDot.firstChild.classList.add("active");
    }
}
init();

//๋งค๊ฐœ๋ณ€์ˆ˜ ์‚ฌ์šฉ - 5๋ฒˆ ์Šฌ๋ผ์ดํŠธ ์ดํŽ™ํŠธ ๋ณด๋‹ค ์„ธ๋ถ„ํ™” ์‹œํ‚ค๊ธฐ
function gotoSlider(direction){
    sliderInner.classList.add("transition");
    // ์Šฌ๋ผ์ด๋“œ ๋ฒ„ํŠผ ์—ฐ์†์œผ๋กœ ๋ˆ„๋ฅผ ์ˆ˜ ์—†๊ฒŒ ํ•˜๊ธฐ 02
    sliderBtn.classList.add("disable");

    posInital = sliderInner.offsetLeft;
    // console.log(posInital);

    //direction์ด๋ผ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์— -1์ด ๋“ค์–ด์˜จ๋‹ค๋ฉด ์™ผ์ชฝ์œผ๋กœ ์ด๋™(์ด์ „) ๋˜ํ•œ 1์ด๋ผ๋ฉด ์˜ค๋ฅธ์ชฝ์œผ๋กœ ์ด๋™(๋‹ค์Œ)
    if(direction == -1){
        // sliderInner.style.left = "800px"; //์™ผ์ชฝ์œผ๋กœ 800๋งŒํผ ์›€์ง์ด๊ธฐ
        //๋ถ€๋ชจ๋ฐ•์Šค offsetLeft๊ฐ’์„ ๊ตฌํ•˜์—ฌ ๋”ํ•˜๋Š” ์ด์œ ๋Š”? sliderWidth๋Š” ์Šฌ๋ผ์ด๋” ํ•˜๋‚˜๋งŒ์˜ ๊ฐ€๋กœ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋™์‹œ ๋Š˜์–ด๋‚˜๊ฑฐ๋‚˜ ์ค„์–ด๋“œ๋Š” ๊ฐ’์„ ๊ตฌํ•  ์ˆ˜ ์—†๋‹ค ๋•Œ๋ฌธ์— ๊ทธ ์Šฌ๋ผ์ด๋”๋ฅผ ๊ฐ์‹ธ๋Š” ๋ถ€๋ชจ๋ฐ•์Šค์˜ ๊ฐ€๋กœ๊ฐ’์„ ๊ตฌํ•˜์—ฌ ๋Š˜์–ด๋‚˜๋Š” ๊ฐ’ ๋งŒํผ ๊ธธ์ด๋ฅผ ๋”ํ•˜์—ฌ ์ถ”๊ฐ€์‹œํ‚จ ๊ฒƒ ์ด๋‹ค.
        sliderInner.style.left = (posInital + sliderWidth) + "px"; //์™ผ์ชฝ์œผ๋กœ ์Šฌ๋ผ์ด๋” ๊ฐ€๋กœ๊ฐ’๋งŒํผ ์›€์ง์ด๊ธฐ. ์Šฌ๋ผ์ด๋”์˜ ๋ถ€๋ชจ๋ฐ•์Šค์˜ ์™ผ์ชฝ๊ฐ’์„ ๋”ํ•œ ์ด์œ ๋Š”?
        currentIndex --;

    }else if(direction == 1){

        // sliderInner.style.left = "-800px";                
        sliderInner.style.left = (posInital - sliderWidth) + "px";               
        currentIndex ++;
    }
}

// ์ˆœ๊ฐ„์ด๋™ ์ด๋ฏธ์ง€ ์Šฌ๋ผ์ด๋“œ (๋ฌดํ•œ ์Šฌ๋ผ์ด๋“œ)
function checkIndex(){
    //์Šฌ๋ผ์ด๋“œ๊ฐ€ ๋๋‚˜๋ฉด transition ํด๋ž˜์Šค๋ฅผ ๋‹ค์‹œ ์ง€์›Œ์„œ transitionํšจ๊ณผ๊ฐ€ ๋‚˜์˜ค์ง€ ์•Š๋„๋ก ํ•˜๊ณ  ์ด๋ฏธ์ง€ ์ˆœ๊ฐ„์ด๋™ ์‹œํ‚ค๊ธฐ
    sliderInner.classList.remove("transition"); 
    // console.log(currentIndex);

    if(currentIndex == sliderLength){
        sliderInner.style.left = -(1 * sliderWidth) + "px";
        currentIndex = 0;
    }

    if(currentIndex == -1){
        sliderInner.style.left = -(sliderLength * sliderWidth) + "px";
        currentIndex = sliderLength -1;
    }
}

//์‹คํ–‰๋ฌธ
sliderBtnPrev.addEventListener("click", () => {
    gotoSlider(-1); //๋งค๊ฐœ๋ณ€์ˆ˜ direction์— ๊ฐ’ ์ฃผ๊ธฐ
    setTimeout(() => {
        sliderBtn.classList.remove("disable");
    },300);
});
sliderBtnNext.addEventListener("click", () => {
    gotoSlider(1); //๋งค๊ฐœ๋ณ€์ˆ˜ direction์— ๊ฐ’ ์ฃผ๊ธฐ
    setTimeout(() => {
        sliderBtn.classList.remove("disable");
    },300);
});
// ํŠธ๋ Œ์ง€์…˜ ์ด๋ฒคํŠธ๊ฐ€ ๋๋‚ฌ์„ ๋•Œ ์ผ์–ด๋‚˜๋Š” ์ด๋ฒคํŠธ
sliderInner.addEventListener("transitionend", checkIndex);

#3. ๊ฒฐ๊ณผ ๋ณด๊ธฐ ๐ŸŽ‰

728x90

๋Œ“๊ธ€


Lucky Charms Rainbow
js
html
css