코딩 공부/JAVASCRIPT

패럴랙스 이펙트(parallaxEffect) : 리빌 효과

천서리 2023. 5. 18. 21:50
QUOTE THE DAY

“ 당신이 6개월 이상 한 번도 보지 않은 코드는 다른 사람이 다시 만드는 게 훨씬 더 나을 수 있다. ”

- 이글슨 (Eagleson)
반응형

패럴랙스 이펙트란?

패럴랙스 이펙트는 사용자가 스크롤을 내리거나 올릴 때, 배경과 함께 웹 페이지의 요소들이 서로 다른 속도로 움직이는 것을 말합니다. 이는 일반적으로 CSS와 JavaScript를 사용하여 구현되며, 웹 페이지를 더욱 동적이고 인터랙티브하게 만들어줍니다.

 

웹사이트 패럴랙스 이펙트를 사용하면 사용자가 웹 페이지를 스크롤 할 때, 배경 이미지와 함께 다양한 요소들이 움직이는 것처럼 보입니다. 예를 들어, 웹 페이지에 일러스트나 이미지를 배경으로 사용하면 이를 이용하여 사용자의 눈길을 이끌거나 페이지의 구조를 강조할 수 있습니다. 또는 텍스트나 버튼과 같은 요소들도 패럴랙스 이펙트를 이용하여 동적인 효과를 줄 수 있습니다.

 

패럴랙스 이펙트는 웹 디자인의 트렌드 중 하나로, 사용자 경험을 개선하고 웹 페이지를 더욱 흥미롭고 동적으로 만들어줍니다. 하지만, 지나친 사용은 사용자 경험을 해치고 성능 저하를 일으킬 수 있으므로 적절한 사용이 필요합니다.

 

 

 


패럴랙스 이펙트 사이트 코드

<main id="main">
    <div class="parallax__wrap">
        <section id="section1" class="parallax__item">
            <span class="parallax__item__num">01</span>
            <h2 class="parallax__item__title">Section1</h2>
            <figure class="parallax__item__imgWrap reveal">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal" data-delay="1500">행동이 모든 것을 결정한다. 운명은 행동에서 비롯된다.</p>
        </section>
        <!-- //section1 -->

        <section id="section2" class="parallax__item">
            <span class="parallax__item__num">02</span>
            <h2 class="parallax__item__title">Section2</h2>
            <figure class="parallax__item__imgWrap reveal">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal" data-delay="1500">작은 성공이 큰 성공으로 이어진다.</p>
        </section>
        <!-- //section2 -->

        <section id="section3" class="parallax__item">
            <span class="parallax__item__num">03</span>
            <h2 class="parallax__item__title">Section3</h2>
            <figure class="parallax__item__imgWrap reveal reveal-RTL">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-RTL" data-delay="1500">인생은 결코 공평하지 않다. 그러나 그것을 이길 수 있다.</p>
        </section>
        <!-- //section3 -->

        <section id="section4" class="parallax__item">
            <span class="parallax__item__num">04</span>
            <h2 class="parallax__item__title">Section4</h2>
            <figure class="parallax__item__imgWrap reveal reveal-TTB">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-TTB" data-delay="1500">성취하지 못한 것은 아직 해보지 않은 것뿐입니다.</p>
        </section>
        <!-- //section4 -->

        <section id="section5" class="parallax__item">
            <span class="parallax__item__num">05</span>
            <h2 class="parallax__item__title">Section5</h2>
            <figure class="parallax__item__imgWrap reveal reveal-BTT">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-BTT" data-delay="1500">가장 높은 산은 한 발짝부터 시작된다.</p>
        </section>
        <!-- //section5 -->

        <section id="section6" class="parallax__item">
            <span class="parallax__item__num">06</span>
            <h2 class="parallax__item__title">Section6</h2>
            <figure class="parallax__item__imgWrap reveal reveal-TWO">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-TWO" data-delay="1500">목표를 향한 첫 걸음은 용기이다.</p>
        </section>
        <!-- //section6 -->

        <section id="section7" class="parallax__item">
            <span class="parallax__item__num">07</span>
            <h2 class="parallax__item__title">Section7</h2>
            <figure class="parallax__item__imgWrap reveal reveal-TWO reveal-RTL">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-TWO reveal-RTL" data-delay="1500">우리의 인생은 우리의 생각과 믿음이 결정한다.</p>
        </section>
        <!-- //section7 -->

        <section id="section8" class="parallax__item">
            <span class="parallax__item__num">08</span>
            <h2 class="parallax__item__title">Section8</h2>
            <figure class="parallax__item__imgWrap reveal reveal-TWO reveal-TTB">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-TWO reveal-TTB" data-delay="1500">언제나 새로운 것을 배울 수 있고, 새로운 것을 경험할 수 있다.</p>
        </section>
        <!-- //section8 -->

        <section id="section9" class="parallax__item">
            <span class="parallax__item__num">09</span>
            <h2 class="parallax__item__title">Section9</h2>
            <figure class="parallax__item__imgWrap reveal reveal-TWO reveal-BTT">
                <div class="parallax__item__img"></div>
            </figure>
            <p class="parallax__item__desc reveal reveal-TWO reveal-BTT" data-delay="1500">한계는 우리가 만든 것이며, 우리가 이겨낼 수 있다.</p>
        </section>
        <!-- //section9 -->

    </div>
</main>
<!-- //main -->

 

  1. section 요소의 id 속성은 "section1"로 설정되어 있습니다. id 속성은 요소를 식별하기 위해 사용될 수 있는 고유한 식별자입니다.
  2. class 속성에 "parallax__item" 클래스가 설정되어 있습니다. 클래스는 여러 요소를 그룹화하거나 스타일을 적용하기 위해 사용됩니다.
  3. <span> 요소에 "parallax__item__num" 클래스가 설정되어 있습니다. 이 요소는 섹션의 번호를 나타내기 위해 사용될 수 있습니다.
  4. <h2> 요소에 "parallax__item__title" 클래스가 설정되어 있습니다. 이 요소는 섹션의 제목을 나타내기 위해 사용될 수 있습니다.
  5. <figure> 요소에 "parallax__item__imgWrap" 클래스와 "reveal" 클래스가 설정되어 있습니다. 이 요소는 이미지를 감싸는 컨테이너 역할을 하며, "reveal" 클래스는 스크롤 시 이미지를 표시하기 위한 동적인 효과를 구현하는 데 사용될 수 있습니다.
  6. <div> 요소에 "parallax__item__img" 클래스가 설정되어 있습니다. 이 요소는 실제 이미지를 나타낼 수 있는 공간을 제공할 수 있습니다.
  7. <p> 요소에 "parallax__item__desc" 클래스와 "reveal" 클래스가 설정되어 있습니다. 이 요소는 섹션의 설명을 담고 있으며, "reveal" 클래스는 스크롤 시에 텍스트를 동적으로 표시하는 효과를 구현하는 데 사용될 수 있습니다. 또한, data-delay 속성은 1500밀리초(1.5초)의 지연 시간을 나타내며, 텍스트가 표시되기 전에 대기해야 하는 시간을 설정할 수 있습니다.

위의 코드는 한 섹션을 구성하는 요소들을 나타내며, 각 요소에는 특정 클래스와 데이터 속성이 설정되어 있습니다. 이를 통해 스타일링이나 동적인 효과를 적용할 수 있습니다.


CSS

.reveal > div,
.reveal > span {
    opacity: 0;
}
.reveal.show > div,
.reveal.show > span {
    animation: opacity 1s linear forwards;
}
.reveal {
    position: relative;
}

/* 1개 */
.reveal::before {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 0%;
    height: 100%;
    background-color: #fff;
    z-index: 1;
}
.reveal.show::before {
    animation: reveal 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-RTL.show::before {
    animation: reveal-RTL 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-TTB.show::before {
    animation: reveal-TTB 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-BTT.show::before {
    animation: reveal-BTT 1s cubic-bezier(0.075, 0.82, 0.165, 1);
}
  1. .reveal > div, .reveal > span 선택자는 "reveal" 클래스의 자식인 <div> 요소와 <span> 요소를 선택합니다.
  2. 선택된 요소들의 opacity 속성을 0으로 설정하여 초기에 투명하게 만듭니다.
  3. .reveal.show > div, .reveal.show > span 선택자는 "reveal" 클래스가 있고 "show" 클래스가 추가된 자식 <div> 요소와 <span> 요소를 선택합니다.
  4. 선택된 요소들에 animation 속성을 적용하여 opacity 애니메이션을 1초 동안 선형적으로 적용합니다.
  5. .reveal 클래스에는 position 속성을 relative로 설정합니다.
  6. .reveal::before 선택자는 "reveal" 클래스의 가상 요소인 ::before를 선택합니다.
  7. ::before 가상 요소에는 흰색 배경과 0%의 너비를 가진 절반 높이의 사각형을 생성합니다. 이 사각형은 요소의 왼쪽에 상대적으로 위치합니다.
  8. reveal.show::before 선택자는 "reveal" 클래스가 있고 "show" 클래스가 추가된 ::before 가상 요소를 선택합니다.
  9. 선택된 가상 요소에 animation 속성을 적용하여 reveal 애니메이션을 1초 동안 적용합니다. 이 애니메이션은 cubic-bezier 타이밍 함수를 사용합니다.
  10. .reveal.reveal-RTL.show::before, .reveal.reveal-TTB.show::before, .reveal.reveal-BTT.show::before 선택자들은 특정한 방향(RTL, TTB, BTT)을 가진 "reveal" 클래스에 "show" 클래스가 추가된 ::before 가상 요소를 선택합니다.
  11. 각각의 선택자에 해당하는 가상 요소에는 각각에 맞는 방향 애니메이션을 적용합니다.

 

/* 2개 */
.reveal.reveal-TWO::after {
    content: '';
    position: absolute;
    left: 0;
    top: 0;
    width: 0;
    height: 100%;
    z-index: 1;
    background-color: #45507ca4;
}
.reveal.show::after {
    animation: reveal 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-RTL.show::after {
    animation: reveal-RTL 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-TTB.show::after {
    animation: reveal-TTB 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}

.reveal.reveal-BTT.show::after {
    animation: reveal-BTT 1s 0.3s cubic-bezier(0.075, 0.82, 0.165, 1);
}
  1. .reveal.reveal-TWO::after 선택자는 "reveal" 클래스와 "reveal-TWO" 클래스를 가진 요소의 가상 요소인 ::after를 선택합니다.
  2. ::after 가상 요소는 절반 높이의 사각형으로, 요소의 왼쪽에 상대적으로 위치하며 투명한 상태입니다.
  3. .reveal.show::after 선택자는 "reveal" 클래스와 "show" 클래스가 추가된 ::after 가상 요소를 선택합니다.
  4. 선택된 가상 요소에 animation 속성을 적용하여 reveal 애니메이션을 1초 동안 적용합니다. 이 애니메이션은 0.3초의 지연 시간을 가지며, cubic-bezier 타이밍 함수를 사용합니다.
  5. .reveal.reveal-RTL.show::after, .reveal.reveal-TTB.show::after, .reveal.reveal-BTT.show::after 선택자들은 특정한 방향(RTL, TTB, BTT)을 가진 "reveal" 클래스에 "show" 클래스가 추가된 ::after 가상 요소를 선택합니다.
  6. 각각의 선택자에 해당하는 가상 요소에는 각각에 맞는 방향 애니메이션을 적용합니다.

 

 

/* animation */
@keyframes opacity {
    0%   {opacity: 0;}
    60%  {opacity: 0;}
    70%  {opacity: 1;}
    100% {opacity: 1;}
}

@keyframes reveal {
    0%   {width: 0;    left: 0;}
    50%  {width: 100%; left: 0;}
    80%  {width: 100%; left: 0;}
    100% {width: 0;    left: 100%;}
}

@keyframes reveal-RTL {
    0%   {width: 0;    left: auto; right: 0;}
    50%  {width: 100%; left: auto; right: 0;}
    80%  {width: 100%; left: auto; right: 0;}
    100% {width: 0;    left: auto; right: 100%;}
}

@keyframes reveal-TTB {
    0%   {width: 100%;    height: 0;    top: 0;}
    50%  {width: 100%; height: 100%; top: 0;}
    80%  {width: 100%; height: 100%; top: 0;}
    100% {width: 100%;    height: 0;    top: 100%;}
}

@keyframes reveal-BTT {
    0%   {width: 100%;    height: 0;    bottom: 0;      top: auto;}
    50%  {width: 100%; height: 100%;    bottom: 0;      top: auto;}
    80%  {width: 100%; height: 100%;    bottom: 0;      top: auto;}
    100% {width: 100%;    height: 0;    bottom: 100%;      top: auto;}
}
  1. opacity 애니메이션:
    • 0%부터 60%까지: 투명도를 0으로 설정하여 요소를 투명하게 만듭니다.
    • 70%부터 100%까지: 투명도를 1로 설정하여 요소를 완전히 나타내게 합니다.
  2. reveal 애니메이션:
    • 0%부터 50%까지: 요소의 너비를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
    • 80%까지: 요소의 너비를 100%로 설정하여 요소를 가로 방향으로 전체적으로 펼치게 합니다.
    • 100%까지: 요소의 너비를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 오른쪽 끝으로 이동합니다.
  3. reveal-RTL 애니메이션:
    • 0%부터 50%까지: 요소의 너비를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
    • 80%까지: 요소의 너비를 100%로 설정하여 요소를 가로 방향으로 전체적으로 펼치게 합니다.
    • 100%까지: 요소의 너비를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 오른쪽 끝으로 이동합니다. (RTL은 Right-to-Left의 약자로 오른쪽에서 왼쪽으로 이동하는 효과를 의미합니다.)
  4. reveal-TTB 애니메이션:
    • 0%부터 50%까지: 요소의 높이를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
    • 80%까지: 요소의 높이를 100%로 설정하여 요소를 세로 방향으로 전체적으로 펼치게 합니다.
    • 100%까지: 요소의 높이를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 아래쪽에서 위쪽으로 이동합니다. (TTB는 Top-to-Bottom의 약자로 위에서 아래로 이동하는 효과를 의미합니다.)
  5. reveal-BTT 애니메이션:
    • 0%부터 50%까지: 요소의 높이를 0으로 설정하여 요소를 시작점에서 시작하게 합니다.
    • 80%까지: 요소의 높이를 100%로 설정하여 요소를 세로 방향으로 전체적으로 펼치게 합니다.
    • 100%까지: 요소의 높이를 다시 0으로 설정하여 요소를 끝점에서 사라지게 합니다. 이때 요소는 위쪽에서 아래쪽으로 이동합니다. (BTT는 Bottom-to-Top의 약자로 아래에서 위로 이동하는 효과를 의미합니다.)

JS

 //만약에 reveal 클래스를 추가하면 자식요소에 span으로 감싸주기!
document.querySelectorAll("p.reveal").forEach(text => {
    text.innerHTML = `<span>${text.innerHTML}</span>`
});
  1. document.querySelectorAll("p.reveal")는 HTML 문서에서 "reveal" 클래스를 가진 모든 <p> 요소를 선택합니다.
  2. forEach 메서드는 선택된 각 요소에 대해 반복 작업을 수행합니다.
  3. 반복 작업에서 text.innerHTML을 사용하여 각 요소의 내용을 가져옵니다.
  4. 템플릿 리터럴을 사용하여 새로운 내용을 생성합니다. <span> 요소는 기존 내용을 감싸기 위해 사용됩니다.
  5. text.innerHTML에 새로운 내용을 할당하여 기존 내용을 감싼 <span> 요소로 대체합니다.

 

function scroll(){
    let scrollTop = window.scrollY || window.pageYOffset;

    const reveals = document.querySelectorAll(".reveal");

    reveals.forEach(reveal => {
        let revealOffset = reveal.offsetTop + reveal.parentElement.offsetTop;
        let revealDelay = reveal.dataset.delay;

        // if(scrollTop >= revealOffset - window.innerHeight/2){
        //     reveal.classList.add("show");
        // }

        if(scrollTop >= revealOffset - window.innerHeight){
            if(revealDelay == undefined){
                reveal.classList.add("show");
            } else {
                setTimeout(() => {
                    reveal.classList.add("show");
                }, revealDelay)
            }
        }
    });

    //info
    document.querySelector(".scroll span").innerText = Math.round(scrollTop);
    requestAnimationFrame(scroll);
}
scroll();
  1. scroll 함수는 스크롤 이벤트가 발생할 때 호출되는 함수입니다. 스크롤 위치를 가져오고, 요소를 선택합니다.
  2. scrollTop 변수는 window.scrollY 또는 window.pageYOffset을 통해 현재 스크롤 위치를 가져옵니다.
  3. reveals 변수는 클래스가 "reveal"인 모든 요소를 선택합니다.
  4. reveals.forEach 메서드를 사용하여 선택된 각 요소에 대해 반복 작업을 수행합니다.
  5. revealOffset 변수는 각 요소의 상위 요소에서의 오프셋과 offsetTop을 사용하여 현재 요소의 절대적인 위치를 계산합니다.
  6. revealDelay 변수는 데이터 속성인 data-delay를 사용하여 지연 시간을 가져옵니다.
  7. 주석 처리된 코드 블록은 스크롤 위치가 요소의 위치보다 크거나 같을 때, 해당 요소에 "show" 클래스를 추가하는 기능입니다. 여기서 window.innerHeight/2는 화면의 높이의 절반을 나타냅니다.
  8. 다음 코드 블록은 스크롤 위치가 요소의 위치보다 크거나 같을 때, "show" 클래스를 추가하는데, data-delay 속성이 정의되어 있다면 해당 지연 시간 후에 클래스를 추가합니다.
  9. requestAnimationFrame(scroll)은 애니메이션 프레임을 요청하여 scroll 함수가 연속적으로 호출되도록 합니다. 이로써 스크롤 이벤트가 발생할 때마다 요소가 업데이트됩니다.
  10. 마지막으로, 스크롤 위치를 화면에 표시하기 위해 .scroll span 요소의 내용을 업데이트합니다.

 

 

반응형
Adventure Time - BMO