JAVASCRIPT

패럴렉스 이펙트 리빌 효과

이미사용 2023. 5. 17. 19:07
명언
-
728x90
반응형

리빌효과

전체소스

HTML / CSS

<!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/Parallax.css">
    <style>
        .reveal > div,
        .reveal > span {
            opacity: 0;
        }
        .reveal.show > div,
        .reveal.show > span  {
            animation:  opacity 1s linear forwards;
        }

        .reveal {
            position: relative;
        }
        .reveal::before {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            width: 0;
            height: 100%;
            background-color: #fff;
            z-index: 1;
        }
        .reveal.reveal-TWO::after {
            content: '';
            position: absolute;
            left: 0;
            top: 0;
            width: 0;
            height: 100%;
            z-index: 1;
            background-color: #adadad;
        }

        /* 1개 */
        .reveal.show::before {
            animation: reveal 1s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-RTL.show::before {
            animation: reveal-RTL 1s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-TTB.show::before {
            animation: reveal-TTB 1s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-BTT.show::before {
            animation: reveal-BTT 1s cubic-bezier(0, 0.78, 0.58, 1);
        }
        /* 2개 */
        .reveal.show::after {
            animation: reveal 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-RTL.show::after {
            animation: reveal-RTL 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-TTB.show::after {
            animation: reveal-TTB 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
        }
        .reveal.reveal-BTT.show::after {
            animation: reveal-BTT 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
        }

        /* 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;}
        }
        .Parallax__item__num,
        .Parallax__item__title {
            display: none;
        }
    </style>

</head>
<body class="img05 bg01 font09">
    <header id="header">
        <h1>Javascript Parallax Effect07</h1>
        <p>패럴렉스 이펙트 : 리빌 효과</p>
        <ul>
            <li><a href="parallaxEffect01.html">1</a></li>
            <li><a href="parallaxEffect02.html">2</a></li>
            <li><a href="parallaxEffect03.html">3</a></li>
            <li><a href="parallaxEffect04.html">4</a></li>
            <li><a href="parallaxEffect05.html">5</a></li>
            <li><a href="parallaxEffect06.html">6</a></li>
            <li class="active"><a href="parallaxEffect07.html">7</a></li>
        </ul>
    </header>
    <!-- header -->
    <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">삶은 탐구하는 모험이다.</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">오늘 당신이 할 수 있는 최선의 일을 하라.</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">비난은 쓸모없는 짓이다.</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">우리의 삶은 우리가 생각하는 것처럼 빠르지 않고, 우리가 생각하는 것보다 짧다.</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">머리로 생각하는 것보다는 마음으로 생각하고 행동하라.</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=1000>인생은 문제다. 그것을 해결해 나가는 과정에서 삶이 만들어진다.</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=1000>성공은 단순히 실패를 거듭하고 계속하는 것이다.</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=1000>기회는 항상 어려운 일 모습으로 찾아온다.</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=1000>목표를 지닌 사람들만이 인생에서 진정으로 살아간다.</p>
            </section>
            <!-- //section9-->
        </div>

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

    <aside class="Parallax__info">
        <div class="scroll">scrollTop : <span>0</span>px</div>
    </aside>
    <!-- Parallax__info -->
    <footer id="footer">
        <a href="mailto:ghkddn132@naver.com">ghkddn132@naver.com</a>
    </footer>
    <!-- footer -->

 

JAVASCRIPT

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
    <script>
        //p .reveal 자식요소에 span으로 감싸주세요!!
        document.querySelectorAll("p.reveal").forEach(text => {

            text.innerHTML = `<span>${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; //parentElement는 부모
                let revealDelay = reveal.dataset.delay;
                
                // if(scrollTop >= revealOffset - window.innerHeight){
                //     reveal.classList.add("show")
                // }

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

            document.querySelector(".scroll span").innerText = Math.round(scrollTop);
            requestAnimationFrame(scroll);
        }
        scroll();
    </script>

※재귀 함수를 사용한 클래스에 스크롤값에 반응하여 값 넣기

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>

GSAP 라이브러리를 외부 스크립트로 가져옵니다. 이 라이브러리는 JavaScript 기반의 애니메이션 플러그인으로 많이 사용됩니다.

 

- 클래스가 "reveal"인 모든 <p> 요소를 선택합니다. 그런 다음, 선택된 각 요소에 대해 다음 코드를 실행합니다.
- text.innerHTML = <span>${text.innerHTML}</span>;: 선택된 요소의 내용을 변경하여 <span> 태그로 감싸줍니다.
- 스크롤 이벤트에 대한 처리를 담은 scroll 함수를 실행합니다.
- 현재 스크롤 위치를 scrollTop 변수에 저장합니다. window.scrollY는 모던 브라우저에서, window.pageYOffset는 브라우저에서 스크롤 위치를 가져오는 두 가지 방법을 모두 고려하여 값을 설정합니다.
- 클래스가 "reveal"인 모든 요소를 선택하여 reveals 변수에 저장합니다.
- eveals 요소 목록에 대해 반복문을 실행합니다. 각 요소에 대해 다음 코드를 실행합니다.
- reveal 요소의 상단 위치와 부모 요소의 상단 위치를 합산하여 revealOffset 변수에 저장합니다. 이렇게 함으로써 reveal 요소가 스크롤되었을 때 보여지는 영역을 정의합니다.
- reveal 요소의 data-delay 속성 값을 가져와 revealDelay 변수에 저장합니다. 이 속성은 애니메이션 지연 시간을 정의하는 데 사용됩니다.
- 현재 스크롤 위치가 reveal 요소가 화면에 보여지는 영역을 벗어나지 않는지 확인합니다.
- revealDelay 변수가 정의되지 않았는지 확인하여 애니메이션을 실행합니다. 정의되지 않았다면 즉시 애니메이션을 적용하고, 그렇지 않다면 setTimeout 함수를 사용하여 revealDelay 시간 이후에 애니메이션을 적용합니다.
- 애니메이션을 보여주기 위해 reveal 요소에 "show" 클래스를 추가합니다.
- HTML 문서에서 클래스가 "scroll"인 요소를 선택하고, 그 자식 요소인 <span>의 내용을 현재 스크롤 위치인 scrollTop 값으로 설정합니다.
- scroll 함수를 반복해서 실행하기 위해 requestAnimationFrame 메서드를 사용합니다. 이를 통해 애니메이션이 부드럽게 처리됩니다.

 

requestAnimationFrame  브라우저에게 애니메이션을 수행하기 전에 다음 리페인트까지 애니메이션을 업데이트하고 그리도록 지시하는 메서드입니다. 이 메서드를 사용하면 브라우저의 리페인트 주기에 맞추어 애니메이션을 부드럽게 실행할 수 있습니다.