예제로 공부하기/패럴럭스 효과

패럴럭스 효과

Hyeon been 2023. 4. 18. 22:42

한번씩 읽고 가세요.

“ 지연되는 프로젝트에 인력을 더 투입하면 오히려 더 늦어진다. ”

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90

패럴럭스 효과

 

 

HTML코드

<!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>패럴럭스</title>
    <link rel="stylesheet" href="css/reset.css">
    <link rel="stylesheet" href="css/parallax.css">
</head>

<body class="bg02 img02 font08">
    <header id="header">
        <h1>Javasrcipt parallax Effect01</h1>
        <p>패럴럭스 이펙트 : 메뉴효과</p>
        <ul>
            <li class="active"><a href="parallax01.html">1</a></li>
            <li><a href="parallax02.html">2</a></li>
            <li><a href="parallax03.html">3</a></li>
            <li><a href="parallax04.html">4</a></li>
            <li><a href="parallax05.html">5</a></li>
            <li><a href="parallax06.html">6</a></li>
            <li><a href="parallax07.html">7</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 class="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>
            <!--//section-->
            <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>
            <!--//section-->
            <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><!--//section-->
            <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">삶은 짧고 예술은 길다.
            </section>
            <!--//section-->
            <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>
            <!--//section-->
            <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>
            <!--//section-->
            <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>
            <!--//section-->
            <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>
            <!--//section-->
            <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>
            <!--//section-->
        </div>
    </main>

    <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>#section2 offset() : <span class="offset2">0</span>px</li>
                <li>#section3 offset() : <span class="offset3">0</span>px</li>
                <li>#section4 offset() : <span class="offset4">0</span>px</li>
                <li>#section5 offset() : <span class="offset5">0</span>px</li>
                <li>#section6 offset() : <span class="offset6">0</span>px</li>
                <li>#section7 offset() : <span class="offset7">0</span>px</li>
                <li>#section8 offset() : <span class="offset8">0</span>px</li>
                <li>#section9 offset() : <span class="offset9">0</span>px</li>
            </ul>
        </div>
    </aside>
    <footer id="footer">
        <a href="mailto:esansi@naver.com">esansi@naver.com</a>
    </footer>

이번엔 스크롤 이벤트와 offsettop값을 활용하여 페이지를 만들어보았습니다.

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

            //info
            document.querySelector(".scroll span").innerText = parseInt(scrollTop);


            //for문

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


            //각 scrollTop값에 맞는 메뉴 활성화
            document.querySelectorAll(".parallax__item").forEach((item, index) => {
                if (scrollTop >= item.offsetTop - 2) {
                    document.querySelectorAll(".parallax__nav li").forEach((li) => {
                        li.classList.remove("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"
                    })
                })
            })
        });

window에  addEventListener를 사용해 scroll 효과를 줍니다.

그 안에 변수 scrollTop를 생성합니다. scrollTop은 offset값을 가져오기 위해 3가지 방법 을 사용할수있습니다.

window.pageYOffset || window.scrollY || document.documentElement.scrollTop;

이렇게 세가지가 사용가능합니다.

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

for문을 사용해 info offset{i}에 document.getElementById(section${i}).offsetTop를 사용하여 idsection${i}인 요소의 offsetTop 값을 가져옵니다. 

            document.querySelectorAll(".parallax__item").forEach((item, index) => {
                if (scrollTop >= item.offsetTop - 2) {
                    document.querySelectorAll(".parallax__nav li").forEach((li) => {
                        li.classList.remove("active")
                    });
                    document.querySelector(".parallax__nav li:nth-child(" + (index + 1) + ")").classList.add("active")
                }
            });

그리고 

document.querySelectorAll(".parallax__item")에forEach를 사용합니다.  만약 scrollTop 값이 item.offsetTop-2보다 크거나 작을 경우  .parallax__nav li의 li들에게  classList.remove로 active값을 삭제시켜줍니다.

document.querySelector(".parallax__nav li:nth-child(" + (index + 1) + ")").classList.add("active")

li 자식중  index+1값에 만족하는 li 에게 active를 부여합니다.

그렇게 하면 스크롤 위치 값이 이미지의 위치값보다 커질 경우 nav li에 active가 활성화 됩니다.

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

마지막으로  .parallax__nav li a 를 forEach 문을 활용해 li라고 지명시켜주고 li에 클릭 이벤트를 줍니다.

preventDefault()를 사용하고 이벤트를 중지하고

li.getAttribute("href")에

scrollIntoView() 메소드는 DOM 요소를 스크롤하여 화면에 보이도록 하는 효과를 주고 smooth 를 주어 부드럽게 넘어가게 해줍니다.

 

미션

forEach

document.querySelectorAll(".info ul li").forEach((el,index)=>{
  el.querySelector("span").innerText = document.getElementById(`section${index+1}`).offsetTop;                
})

for in

const arr = document.querySelectorAll(".info ul li")
   for(let index in arr){
      const el = arr[index];
      el.querySelector("span").innerText = document.getElementById(`section${parseInt(index)+1}`).offsetTop;
	}

for of

const arr = document.querySelectorAll(".info ul li");
let index = 0;
for (const el of arr) {
	el.querySelector("span").innerText = document.getElementById(`section${index + 1}`).offsetTop;
	index++;
}