Winnie The Pooh Bear 자바스크립트 패럴랙스 이펙트 01_메뉴효과

배움기록/JAVASCRIPT

자바스크립트 패럴랙스 이펙트 01_메뉴효과

코딩은 처음이라 2023. 4. 19. 00:09

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

- Frederick Philips Brooks
Mythical Man-Month 저자
728x90
반응형

자바스크립트 패럴랙스 이펙트 01_메뉴효과

 

 

 

 

 

💜 parallax Effect01

코드 보기 / 완성 화면

 

 

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

<link rel="stylesheet" href="css/reset.css">
<link rel="stylesheet" href="css/parallax.css">
</head>

<body class="img01 bg01 font10">
<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>
        <li><a href="parallaxEffect07.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 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 -->

<aside class="parallax__info">
    <div class="scroll">scrollTop : <span>0</span>ps</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>
<!-- parallax__info -->

<footer id="footer">
    <a href="mailto:hunmi961119@gmail.com">hunmi961119@gmail.com</a>
</footer>
<!-- //footer -->

reset.css와 parallax.css는 link stylesheet로 연결해줬습니다.

 

구역을 나눠 이미지 메뉴와 이미지, 좌표값 부분을 작업해줬습니다.

 

 

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) {
                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"
                })
            })
        })

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

        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;
</script>

window.addEventListner("ccroll", () => {}); 윈도우 객체의 스크롤 이벤트를 감지하는 이벤트 리스너를 사용해줬습니다.

let scrollTop = window.pageY0ffset || window.scrollY || documentElement.scrollTop; 스크롤이 발생한 위치를 가져오기 위해 pageYoffset, scrollY, documentElement.scrollTop 세 가지 속성을 사용해 현재 스크롤 위치를 계산하고 scrollTop 변수에 할당합니다.

 

document.querySelectorAll(".parallax__item").forEach(item, index) => {}); 클래스 이름이 parallax__item 인 모든 요소들을 선택해 forEach 루프를 사용해 각 요소에 대해 처리를 수행합니다.

이 부분은 각 섹션이 스크롤 위치를 확인하고 활성화 상태를 변경하는 로직이 구현되어 있습니다.

 

if (scrollTop >= item.offsetTop -2) {} 스크롤 위치가 각 섹션의 위치보다 크거나 같으면, 해당 섹션의 인덱스를 기반으로 메뉴의 활성화 상태를 변경

-2를 빼는 이유는 약간의 여유를 주기 위함입니다.

 

document.querySelector(".parallax__nav li:nth-child(" + (index + 1)+ ")").classList.add("active"); 현재 활성화된 섹션의 인덱스를 기반으로 해당 메뉴 아이템의 클래스에 active 를 추가해 활성화 표시를 합니다.

 

document.querySelector(li.getAttribute("href")).scrollIntoView({behavior: "smooth"}); 클릭된 메뉴 아이템의 href 속성을 기반으로 해당 섹션의 요소를 선택해 scrollIntoView()메서드를 사용해 부드러운 스크롤로 해당 섹션으로 이동합니다.

 

반복문은 for문과 for Each문 for in문 for of문으로 바꿔주겠습니다.

for문

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

반복문을 사용해

offsetTop값을 가져와 info .offset1부터 info .offset9 라는 클래스들의 텍스트 내용으로 설정합니다.

offsetTop 값을 .info 클랙스 하위의 offset1부터 offset9 라는 클래스들에 각각 출력합니다.

 

forEach문

document.querySelectorAll(".info span").forEach((e, i) => {
    e.innerHTML = document.getElementById(`section${i + 1}`).offsetTop;
});

document.querySelectorAll 메서드를 사용해 .info 클래스 내부에 있는 span 요소들을 선택하고

forEach메서드를 사용해 각각의 span요소에 대해 콜백 함수를 실행하는 코드입니다.

 

 

for in 문

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

for (let i in infoSpans) {
    const e = infoSpans[i];
    e.innerHTML = document.getElementById(`section${parseInt(i) + 1}`).offsetTop;
}

for in 루프를 사용해 infoSpans 에 저장된 span요소들을 순환

let i in infoSpans 은 infoSpans의 인덱스를 i라는 변수에 할당

const e = infoSpans[i]는 현재 순회 중인 span 요소를 e 라는 상수에 저장

 

document.getElementById(`section${parseInt(i)+1}`).offsetTop은 section 이라는 ID를 가진 요소들 중에 i에 1을 더한 값을 ID로 가지는 요소의 offsetTop 값을 가져옵니다.

 

for of문

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

for (const e of infoSpans) {
    const index = Array.from(infoSpans).indexOf(e);
    e.innerHTML = document.getElementById(`section${index + 1}`).offsetTop;
}

for of 문을 사용해 infoSpans에 저장된 span 요소들을 순회

const e of infoSpan 는 infoSpans의 각 span 요소를 e 라는 상수에 할당합니다.

 

Array.form(infoSpans)는 infoSpans 를 배열로 변환합니다.

-indexOf 메소드를 사용하기 위해

 

const index = Array.from(infoSpans).indexOf(e)는 현재 순회중인 span 요소의 인덱스를 구합니다.

 

document.getElementById(`section${index + 1}`).offsetTop 은 section 이라는 ID를 가지 요소들 중에 index에 1을 더한 값을 ID로 가지는 요소의 offsetTop 값을 가져옵니다.

 

e.innerHTML = document.getElementById(`section${index + 1}`).offsetTop 은 현재 순회중인 span 요소의 내용을 해당 section 요소의 offsetTop 값으로 설정, .info 클래스를 가진 요소의 자식span 요소들의 내용이 각각의 section 요소의 offsetTop 값으로 표시

반응형