Fast Blinking Hello Kitty

JAVASCRIPT

parallaxEffect 만들기

코른이되고싶은코린이 2023. 4. 18. 15:33

728x90

parallax 효과 만들기

메뉴

코드블럭

<!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>패럴랙스 이펙트01</title>

    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/parallax.css">
</head>
<body class="img01 bg01 font01">
    <header id="header">
        <h1>Javascript parallax Effect01</h1>
        <p>패럴랙스 이펙트: 메뉴 효과</p>
        <ul>
            <li class="active"><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>
        </ul>
    </header>
    <!--header  -->

    <nav class="parallax__nav">
        <ul>
            <li class="active"><a href="#section1">메뉴1</a></li>
            <li><a href="#section2">메뉴2</a></li>
            <li><a href="#section3">메뉴3</a></li>
            <li><a href="#section4">메뉴4</a></li>
            <li><a href="#section5">메뉴5</a></li>
            <li><a href="#section6">메뉴6</a></li>
            <li><a href="#section7">메뉴7</a></li>
            <li><a href="#section8">메뉴8</a></li>
            <li><a href="#section9">메뉴9</a></li>
        </ul>
    </nav>
    <!-- parallax__nav -->

    <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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">결과도 중요하지만, 과정을 더 즁요하게 생각한다.</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">세상 모든 일은 여러분이 무엇을 생각하느냐에 따라 일어납니다.</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">웃음은 두 사람간의 가장 가까운 거리다</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">지속적인 긍정적 사고는 능력을 배가시킨다.</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">정의는 외부에서 오는 것이 아니라 내적 평온으로부터 온다.</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">아무것도 변하지 않을지라도 내가 변하면 모든 것이 변한다</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">노력을 이기는 재능은 없고 노력을 외면하는 결과도 없다</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">사소한 것들을 소중히 해야한다. 그것이 삶을 이루는 버팀목이니까</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">
                    <div class="parallax__item__img"></div>
                </figure>
                <p class="parallax__item__desc">때론 기회를 놓치는 것이 기회일 수 있다.</p>
            </section>
            <!--//section9-->
        </div>
    </main>
    <!-- main -->
    <footer id="footer">
        <a href="mailto:lee3ll@naver.com">lee3ll@naver.com</a>
    </footer>

    <aside class="parallax__info">
        <div class="scroll">scrollTop : <span>0</span>px</div>
        <div class="info">
            <ul>
                <li>#section1 offset() : <span class="offset1">0</span>px</li>
                <li>#secrion2 offset() : <span class="offset2">0</span>px</li>
                <li>#secrion3 offset() : <span class="offset3">0</span>px</li>
                <li>#secrion4 offset() : <span class="offset4">0</span>px</li>
                <li>#secrion5 offset() : <span class="offset5">0</span>px</li>
                <li>#secrion6 offset() : <span class="offset6">0</span>px</li>
                <li>#secrion7 offset() : <span class="offset7">0</span>px</li>
                <li>#secrion8 offset() : <span class="offset8">0</span>px</li>
                <li>#secrion9 offset() : <span class="offset9">0</span>px</li>
            </ul>
        </div>
    </aside>
</body>
</html>

script 코드블럭

<script>
        window.addEventListener("scroll", () => {
            let scrollTop = window.pageYOffset //|| window.scrollY || document.documentElement.scrollTop;

            document.querySelectorAll(".parallax__item").forEach((item, index) => {
                if(scrollTop >= item.offsetTop -2){
                    // 메뉴바에서 모든 active 제거
                    document.querySelectorAll(".parallax__nav li").forEach((li) => {
                        li.classList.remove("active");
                    });
                    // active 활성화
                    document.querySelector(".parallax__nav li:nth-child("+(index+1)+")").classList.add("active");
                }
            });

            document.querySelectorAll(".parallax__nav li a").forEach(li=>{
                li.addEventListener("click", (e) => {
                    e.preventDefault();
                    document.querySelector(li.getAttribute("href")).scrollIntoView({
                        behavior:"smooth"
                    })
                });
            });
            
            //info
            const scroll = document.querySelector(".scroll span");

            scroll.innerHTML = Math.floor(scrollTop); //Math.floor() // parseInt() 소수점 안보이게

            // document.querySelector(".info .offset1").innerText = document.getElementById("section1").offsetTop;
            // document.querySelector(".info .offset2").innerText = document.getElementById("section2").offsetTop;
            // document.querySelector(".info .offset3").innerText = document.getElementById("section3").offsetTop;
            // document.querySelector(".info .offset4").innerText = document.getElementById("section4").offsetTop;
            // document.querySelector(".info .offset5").innerText = document.getElementById("section5").offsetTop;
            // document.querySelector(".info .offset6").innerText = document.getElementById("section6").offsetTop;
            // document.querySelector(".info .offset7").innerText = document.getElementById("section7").offsetTop;
            // document.querySelector(".info .offset8").innerText = document.getElementById("section8").offsetTop;
            // document.querySelector(".info .offset9").innerText = document.getElementById("section9").offsetTop;
        });

        const spans = document.querySelectorAll(".info span");

        // for(let i=1; i<10; i++){
        //     document.querySelector(`.info .offset${i}`).innerText = document.getElementById(`section${i}`).offsetTop;
        // };

        // for문
        // for(let i=0; i<=8; i++){
        //     spans[i].innerHTML = document.getElementById("section" + (i+1) ).offsetTop;
        // }

        // forEach 문
        spans.forEach((el, i) => {
            el.innerHTML = document.getElementById(`section${i+1}`).offsetTop;
        });

        // for in 문
        // for(let index in spans){
        //     if(index.match(/[a-z]/) == null){
        //         spans[parseInt(index)].innerHTML = document.getElementById(`section${parseInt(index)+1}`).offsetTop;
        //     }
        // }

        // for of 문
        // {
        //     let index = 0;
        //     for(let span of spans){
        //         span.innerHTML = document.getElementById(`section${index+1}`).offsetTop;
        //         index++;
        //     }
        // }

    </script>

보충설명

✨aside 태그: 오른쪽 사이드에 고정된 정보 영역입니다. 스크롤 위치를 나타내는 scrollTop과, 섹션들의 위치(offset) 정보를 보여주는 ul 태그로 구성되어 있습니다.

 

window.addEventListener: 윈도우 창이 스크롤될 때 발생하는 이벤트에 대한 리스너입니다.

 

document.querySelectorAll: 문서에서 지정한 모든 CSS 선택자를 가진 요소들을 찾습니다.

 

item.offsetTop: item이란 클래스명을 가진 요소의 맨 위쪽으로부터 떨어진 거리를 반환합니다.

 

if(scrollTop >= item.offsetTop -2): 현재 스크롤 위치가 item의 위치에서 2px 이상 내려간 경우

document.querySelectorAll(".parallax__nav li"): .parallax__nav 클래스를 가진 모든 li 요소를 찾습니다.

 

li.classList.remove: 해당 요소의 classList에서 'active' 클래스를 삭제합니다.

 

document.querySelector: CSS 선택자를 이용해 요소를 찾습니다.

 

li.getAttribute("href"): li 요소의 href 속성 값을 반환합니다.

 

document.querySelector(li.getAttribute("href")).scrollIntoView: href 값으로 지정된 요소를 찾아 브라우저 화면에서 보여지도록 스크롤합니다. 스크롤 애니메이션 효과를 적용합니다.

 

for문에서는 i라는 변수를 0부터 8까지 1씩 증가시키면서 spans라는 배열에서 i번째 span 요소를 선택하고, 그 요소의 innerHTML 값에 document.getElementById("section" + (i+1) ).offsetTop 값을 대입합니다. 이렇게 하면 spans[0]~spans[8]까지의 각각의 요소에 해당하는 section의 offsetTop 값을 출력하게 됩니다.

 

 forEach 문에서는 spans 배열의 각 요소를 el로, 해당 요소의 인덱스를 i로 받아옵니다. 그리고 각 요소의 innerHTML 값을 document.getElementById(section${i+1}).offsetTop 값으로 대체합니다. 이 코드는 for문과 같은 기능을 하지만, forEach 메서드를 사용하므로 더 간결하게 코드를 작성할 수 있습니다.