Giant Danio Fish
본문 바로가기
Javascript_Effect

패럴랙스 이펙트 - 사이드 메뉴

by 코딩왕자 2022. 9. 8.

패럴랙스 효과

패럴랙스 이펙트 - 사이드 메뉴

이번에는 메뉴바를 오른쪽 사이드에 두고 반응형 효과를 주어서 이쁜 사이드 메뉴를 만들어 보겠습니다.


결과


HTML 작성

HTML 구조는 예제1번과 같고, 상단에 있던 메뉴바를 사이드 메뉴로 만들었습니다.

소스 보기
<main id="parallax__cont">
    <div id="contents">
        <section id="section1" class="content__item">
            <span class="content__item__num">01</span>
            <h2 class="content__item__title">section1</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">산다는것 그것은 치열한 전투이다.</p>
        </section>
        <!-- //section1 -->
  
        <section id="section2" class="content__item">
            <span class="content__item__num">02</span>
            <h2 class="content__item__title">section2</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">하루에 3시간을 걸으면 7년 후에 지구를 한바퀴 돌 수 있다.</p>
        </section>
        <!-- //section2 -->
  
        <section id="section3" class="content__item">
            <span class="content__item__num">03</span>
            <h2 class="content__item__title">section3</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">내일은 내일의 태양이 뜬다.</p>
        </section>
        <!-- //section3 -->
  
        <section id="section4" class="content__item">
            <span class="content__item__num">04</span>
            <h2 class="content__item__title">section4</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">배고픈 자 밥솥을 열어라.</p>
        </section>
        <!-- //section4 -->
  
        <section id="section5" class="content__item">
            <span class="content__item__num">05</span>
            <h2 class="content__item__title">section5</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">그대 자신의 영혼을 탐구하라.</p>
        </section>
        <!-- //section5 -->
  
        <section id="section6" class="content__item">
            <span class="content__item__num">06</span>
            <h2 class="content__item__title">section6</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">돈이 없는 것은 죄다.</p>
        </section>
        <!-- //section6 -->
  
        <section id="section7" class="content__item">
            <span class="content__item__num">07</span>
            <h2 class="content__item__title">section7</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">무전 유죄, 유전 무죄</p>
        </section>
        <!-- //section7 -->
  
        <section id="section8" class="content__item">
            <span class="content__item__num">08</span>
            <h2 class="content__item__title">section8</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">내 주머니의 푼돈이 남 주머니에 있는 거금보다 낫다.</p>
        </section>
        <!-- //section8 -->
  
        <section id="section9" class="content__item">
            <span class="content__item__num">09</span>
            <h2 class="content__item__title">section9</h2>
            <figure class="content__item__imgWrap">
                <div class="content__item__img"></div>
            </figure>
            <p class="content__item__desc">최고에 도달하려면 최저에서 시작하라.</p>
        </section>
        <!-- //section9 -->
    </div>
</main>

<aside id="parallax__info">
  <div class="scroll">scrollTop : <span>0</span>px</div>
</aside>

CSS 작성

사이드 메뉴 디자인을 해봤습니다. active가 있을 때, 없을 때로 디자인했습니다.

소스보기
/* parallax__nav */
#parallax__nav {
    position: fixed;
    right: 20px;
    top: 20px;
    z-index: 2000;
    background-color: rgba(0, 0, 0, 0.4);
    padding: 20px 30px;
    border-radius: 50px;
}
#parallax__nav li {
    display: inline;
    margin: 0 5px;
}
#parallax__nav li a {
    display: inline-block;
    height: 30px;
    padding: 5px 20px;
    text-align: center;
    line-height: 30px;
}
#parallax__nav li.active a {
    background: #fff;
    color: #000;
    border-radius: 20px;
    box-sizing: content-box;
}
#parallax__cont {
    max-width: 1600px;
    width: 98%;
    margin: 0 auto;
    /* background-color: rgba(255, 255, 255, 0.1); */
}
.content__item {
    width: 1000px;
    max-width: 70vw;
    margin: 30vw auto;
    /* background-color: rgba(255, 255, 255, 0.3); */
    text-align: left;
    margin-right: 0;
    position: relative;
    padding-top: 8vw;
}
.content__item:nth-child(even) {
    margin-left: 0;
    text-align: right;
}
.content__item__num {
    font-size: 35vw;
    font-weight: 100;
    font-family: 'Lato';
    position: absolute;
    left: -5vw;
    top: -13vw;
    opacity: 0.07;
    z-index: -2;
}
.content__item:nth-child(even) .content__item__num {
    left: auto;
    right: -5vw;
}
.content__item__title {
    font-weight: 400;
    text-transform: capitalize;
}
.content__item__imgWrap {
    width: 100%;
    padding-bottom: 56.25%;
    background: #000;
    position: relative;
    overflow: hidden;
    z-index: -1;
}
.content__item__img {
    position: absolute;
    background: url(../assets/img/effect_bg19@2x.jpg);
    background-repeat: no-repeat;
    background-position: center center;
    background-size: cover;
    width: 110%;
    height: 110%;
    left: -5%;
    top: -5%;
    filter: saturate(0%);
    transition: all 1s;
}
.content__item:nth-child(1) .content__item__img {
    background-image: url(../assets/img/effect_bg18@2x.jpg);
}
.content__item:nth-child(2) .content__item__img {
    background-image: url(../assets/img/effect_bg19@2x.jpg);
}
.content__item:nth-child(3) .content__item__img {
    background-image: url(../assets/img/effect_bg20@2x.jpg);
}
.content__item:nth-child(4) .content__item__img {
    background-image: url(../assets/img/effect_bg17@2x.jpg);
}
.content__item:nth-child(5) .content__item__img {
    background-image: url(../assets/img/effect_bg16@2x.jpg);
}
.content__item:nth-child(6) .content__item__img {
    background-image: url(../assets/img/effect_bg15@2x.jpg);
}
.content__item:nth-child(7) .content__item__img {
    background-image: url(../assets/img/effect_bg14@2x.jpg);
}
.content__item:nth-child(8) .content__item__img {
    background-image: url(../assets/img/effect_bg13@2x.jpg);
}
.content__item:nth-child(9) .content__item__img {
    background-image: url(../assets/img/effect_bg12@2x.jpg);
}
.content__item__desc {
    font-size: 4vw;
    line-height: 1.4;
    margin-top: -4vw;
    margin-left: -4vw;
    word-break: keep-all;
}
.content__item:nth-child(even) .content__item__desc {
    margin-left: auto;
    margin-right: -4vw;
}
#parallax__info {
    position: fixed;
    left: 20px;
    bottom: 20px;
    z-index: 2000;
    background-color: rgba(0,0,0,0.4);
    color: #fff;
    padding: 20px;
    border-radius: 10px;
}
#parallax__info li,
.scroll {
    line-height: 1.4;
}
@media (max-width: 800px) {
    #parallax__cont {
        margin-top: 70vw;
    }
    #parallax__nav {
        padding: 10px;
        right: auto;
        left: 10px;
        top: 50%;
        transform: translateY(-50%);
        border-radius: 5px;
        background-color: rgba(0,0,0,0.8);
    }
    #parallax__nav li {
        display: block;
        margin: 5px;
    }
    #parallax__nav li a {
        font-size: 14px;
        padding: 5px;
        border-radius: 5px;
        height: auto;
        line-height: 1;
    }
    #parallax__nav li.active a {
        border-radius: 5px;
    }
    #parallax__info {
        left: 10px;
        bottom: 10px;
    }
}
#parallax__dot {
    position: fixed;
    right: 20px;
    top: 50%;
    transform: translateY(-50%);
    z-index: 10000;
    background: rgba(0,0,0,0.4);
    padding: 20px 10px;
    border-radius: 30px;
}
#parallax__dot li {
    position: relative;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    margin: 12px 8px;
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0);
    transition: box-shadow 0.2s ease;
}
#parallax__dot li a {
    background: #fff;
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    border-radius: 50%;
    transition: transform 0.2s ease;
}
#parallax__dot li span {
    display: none;
}
#parallax__dot li.active {
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 1);                
}
#parallax__dot li.active a {
    transform: scale(0.4);             
}

JS 작성

1번과 큰 구조는 달라진게 없습니다. 내려갈 때 스무스 효과를 주고, 처음 active 값을 모두 제거하고, offsetTop값이 각각 섹션보다 크거나 같을 때 active를 추가해줍니다. 스타일 css 선언으로 active가 있을 때 디자인과 배경을 바꿔주면 완성!. 자세한 설명은 주석에 추가하였습니다.

소스보기
document.querySelectorAll("#parallax__dot a").forEach(el => {
    el.addEventListener("click", e => {
        e.preventDefault();                     /*클릭하면 이동하는것을 중지합니다*/
        
        document.querySelector(el.getAttribute("href")).scrollIntoView({behavior: "smooth"});          /*스무스 하게 이동을 설정합니다*/
    });
});
  
window.addEventListener("scroll", ()=> {
    let scrollTop = window.pageYOffset || window.scrollY || document.documentElement.scrollTop;           /*스크롤 값 선언*/
  
    document.querySelector("#parallax__info span").innerText = Math.floor(scrollTop);        /*스크롤값 버림으로 나온 값을 넣어줍니다.*/
  
    document.querySelectorAll(".content__item").forEach((e, i)=>{
        if(scrollTop >= e.offsetTop - window.innerHeight/2 ){           /*정확히 안맞을수도 있어서 오차가 있을수 있으므로 현재보이는 화면크기값/2를 빼줍니다.*/
            document.querySelectorAll("#parallax__dot li").forEach(li => {
                li.classList.remove("active");
            })
            document.querySelector("#parallax__dot li:nth-child("+(i+1)+")").classList.add("active")          /*i값은 index값이므로 0부터 시작해서 1을 더해줍니다.*/
        };
    });
});
  
  
  
// window.scroll(0, 1000);                 1000에 간다 (고정)
// window.scroll({left: 0, top: 2000});    2000에 간다 (고정)
// window.scroll({left: 0, top: 2000, behavior: "smooth"});  2000에 간다(스무스하게) 고정

// window.scrollTo(0, 1000);                 1000에 간다 (고정)
// window.scrollTo({left: 0, top: 2000});    2000에 간다 (고정)
// window.scrollTo({left: 0, top: 2000, behavior: "smooth"});  2000에 간다(스무스하게) 고정

// window.scrollBy(0, 1000);                 1000에 간다 (고정)
// window.scrollBy({left: 0, top: 2000});    2000에 간다 (고정)
// window.scrollBy({left: 0, top: 2000, behavior: "smooth"});  2000에 간다(스무스하게) 고정

오늘의 코드

Event.preventDefault() : 이벤트를 명시적으로 처리하지 않은 경우, 해당 이벤트에 대한 사용자 에이전트의 기본 동작을 실행하지 않도록 지정합니다.
ex) a태그 같이 링크를 걸어두는곳에 addEventListener를 사용해 click 이벤트를 처리해도 preventDefault를 사용하면 아무 동작을 실행하지 않도록 할수 있습니다.

댓글


광고 준비중입니다