본문 바로가기
JAVASCRIPT

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

by dongjin6539 2023. 5. 17.
728x90
반응형

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

 

수업 시간에 배운 내용을 복습하면서 해보겠습니다.

코드 보기(HTML, JAVASCRIPT / CSS1 / CSS2) / 완성화면

 

 

 

코드 블럭

<!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%;
            background-color: #ff9203;
            z-index: 1;
        }

        /* 1개 */
        .reveal.show::before {
            animation: reveal 1s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-RTL.show::before {
            animation: reveal-RTL 1s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-TTB.show::before {
            animation: reveal-TTB 1s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-BBT.show::before {
            animation: reveal-BBT 1s cubic-bezier(0, 0.6, 0, 1.03);
        }

        /* 2개 */
        .reveal.show::after {
            animation: reveal 1s 0.5s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-RTL.show::after {
            animation: reveal-RTL 1s 0.5s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-TTB.show::after {
            animation: reveal-TTB 1s 0.5s cubic-bezier(0, 0.6, 0, 1.03);
        }
        .reveal.reveal-BBT.show::after {
            animation: reveal-BBT 1s 0.5s cubic-bezier(0, 0.6, 0, 1.03);
        }

        /* 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-BBT {
            0%   {width: 100%; height: 0;    top: auto; bottom: 0;}
            50%  {width: 100%; height: 100%; top: auto; bottom: 0;}
            80%  {width: 100%; height: 100%; top: auto; bottom: 0;}
            100% {width: 100%; height: 0;    top: auto; bottom: 100%;}
        }

        .parallax__item__num,
        .parallax__item__title {
            display: none;
        }
    </style>
</head>
<body class="font03">
    <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 class="main">
        <div class="parallax__wrap">
            <section id="section1" class="parallax__item">
                <span class="parallax__item__num">01</span>
                <h2 class="parallax__item__title">Section01</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>
            <!-- //section1 -->

            <section id="section2" class="parallax__item">
                <span class="parallax__item__num">02</span>
                <h2 class="parallax__item__title">Section02</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">Section03</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">Section04</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">Section05</h2>
                <figure class="parallax__item__imgWrap reveal reveal reveal-BBT">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc reveal reveal reveal-BBT">먼저 자신을 비웃어라. 다른 사람이 당신을 비웃기 전에</p>
            </section>
            <!-- //section5 -->

            <section id="section6" class="parallax__item">
                <span class="parallax__item__num">06</span>
                <h2 class="parallax__item__title">Section06</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">Section07</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">자신감 있는 표정을 지으면 자신감이 생긴다.</p>
            </section>
            <!-- //section7 -->

            <section id="section8" class="parallax__item">
                <span class="parallax__item__num">08</span>
                <h2 class="parallax__item__title">Section08</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">꿈을 계속 간직하고 있으면 반드시 실현할 때가 온다.</p>
            </section>
            <!-- //section8 -->

            <section id="section9" class="parallax__item">
                <span class="parallax__item__num">09</span>
                <h2 class="parallax__item__title">Section09</h2>
                <figure class="parallax__item__imgWrap reveal reveal-TWO reveal-BBT">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc reveal reveal-TWO reveal-BBT">행복은 습관이다. 그것을 몸에 지니라</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:dongjin6539@naver.com">dongjin6539@naver.com</a>
    </footer>
    <!-- //footer -->
</body>
</html>

구성

  • header 태그를 사용해서 제목과 목록을 태그를 사용해 각각 만들어줍니다.
  • nav 태그를 사용해서 메뉴 목록을 태그를 사용해서 만들어줍니다.
  • main 태그를 사용해서 구역 안에 section 태그를 사용해서 각각 알맞는 구성의 태그와 텍스트를 입력해줍니다.
  • aside 태그를 사용해서 section 태그의 좌표 값을 입력해주게끔 만들어줍니다. 
  • 추가로 필요한 css style은 직접 입력해줍니다.

CSS

JAVASCRIPT

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
<script>
    // 만약에 reveal 클래스를 추가하면 자식요소를 span으로 감싸주세요!!
    document.querySelectorAll(".parallax__item__desc.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;
            let revealDelay = reveal.dataset.delay;

            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>

자바스크립트 구성

  • 먼저 scroll할 때 스크롤의 높이값을 구해줍니다. 그러기 위해서는 3가지 방법이 있습니다. window.scrollY || window.pageYOffet || document.documentElement.scrollTop 있습니다.
  • 다음 class 이름이 reveal이 붙어있는 곳을 선택자로 가져와서 forEach( )를 사용해서 각각의 부분에 높이 값을 구해줍니다.  하지만 스트롤 높이 값이 브라우저부터 가져오는 것이 아닌 그곳의 부모까지만 가져오고 부모에서 필요한 부분의 스크롤 높이 값을 더해줘야만 정확한 위치가 나옵니다. 그러므로 reveal.offsetTop + reveal.parentElement.offsetTop의 식을 작성해줍니다.  parentElement를 사용해서 부모 태그를 가져옵니다.
  • 다음 if문을 사용해서 scrollTop의 값이 reveal의 Top값 보다 크거나 같으면 show라는 class 이름을 추가시켜줍니다. 하지만 그냥 reveal의 Top로 입력하면 브라우저의 상단에 도달했을 때 나오기때문에 이미 내용이 지나갈 수 있습니다. 그래서 조건문에 window.innerHeight를 빼줍니다.
  • 그리고 html에 부분에 data-delay의 값이 있으면 delay를 주기 위해 delay값을 가져오기 위해 dataset.delay를 입력해서 가져오고 저장해줍니다. 그러면 입력되지 않은 부분은 undefined가 나옵니다. 그래서 if문으로 delay의 값이 undefined이면 show class를 추가시켜주고 아니면 setTimeout( )으로 1번만 작동하게 해주고 시간을 가져온 delay의 값을 입력해주고 show class를 추가시켜줍니다.

참고

requestAnimationFrame( )
웹 브라우저에서 제공하는 JavaScript 메서드로, 애니메이션 및 그래픽 업데이트에 사용됩니다.
requestAnimationFrame을 사용하면 더 효율적이고 부드러운 애니메이션을 구현할 수 있습니다. 이는 브라우저의 최적화된 업데이트 주기에 맞추어 애니메이션을 동작시키기 때문입니다.
애니메이션을 구현하는 동안 브라우저가 애니메이션에 대한 업데이트를 할 때마다 콜백 함수가 호출됩니다. 이를 통해 브라우저가 현재 화면 갱신 주기에 맞춰 최적화된 업데이트를 수행하고, 화면 플리커링이나 성능 저하를 방지할 수 있습니다.
  • 사용 방법
  1. requestAnimationFrame을 사용하여 애니메이션 콜백 함수를 호출합니다.
  2. 콜백 함수 내에서 애니메이션을 구현합니다.
  3. 애니메이션이 완료되지 않았다면 다음 프레임을 요청하도록 다시 requestAnimationFrame을 호출합니다.

 

728x90
반응형