패럴렉스 효과
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 Eulyoo">
<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">5</a></li>
<li><a href="parallaxEffect07.html">5</a></li>
</ul>
</header>
<!-- header -->
<nav class="parallax__nav">
<ul>
<li class="active"><a href="#section1">메뉴1</a></li> <!-- li*9>a[href="#section$"]{메뉴$} -->
<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>
<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">하루에 3시간을 걸으면 7년 후에 지구를 한바퀴 돌 수 있다.</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">1퍼센트의 가능성, 그것이 나의 길이다. </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>px</div>
<div class="info">
<ul>
<!-- li*9{#section$ offset() : }>span.offset${px} -->
<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:kshkmn0929@naver.com">kshkmn0929@naver.com</a>
</footer>
<!-- footer -->
HTML 설명
패럴랙스 이펙트를 만들기 위한 html 코드입니다.
JAVSCRIPT
<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;
});
//for
// for(i=1; i<10; i++){
// document.querySelector(".info .offset"+i).innerText = document.getElementById("section"+i).offsetTop
// }
//forEach
// document.querySelectorAll('.info li').forEach((el, i) => {
// document.querySelector(".info .offset"+(i+1)).innerText = document.getElementById("section"+(i+1)).offsetTop;
// });
//for in
// for(let i in document.querySelectorAll(".info li")){
// document.querySelector(".info .offset"+(parseInt(i)+1)).innerText = document.getElementById("section"+(parseInt(i)+1)).offsetTop;
// }
//for of
for (const [i, el] of document.querySelectorAll(".info li span").entries()){
el.innerHTML = document.getElementById("section"+(parseInt(i)+1)).offsetTop;
}
</script>
코드 설명
우선, window.addEventListener("scroll", () => {...} 부분에서는 스크롤 이벤트를 감지하고 해당 이벤트가 발생할 때마다 콜백 함수가 실행됩니다.
그리고 let scrollTop = window.pageYOffset || window.scrollY || document.documentElement.scrollTop; 코드에서는 현재 스크롤바가 위치한 높이 값을 가져옵니다. 이 값은 window.pageYOffset 또는 window.scrollY 또는 document.documentElement.scrollTop 중 하나의 값이 됩니다.
그 다음 document.querySelectorAll(".parallax__item").forEach((item, index) => {...} 부분에서는 각각의 .parallax__item 요소를 순회하며 현재 스크롤 위치를 기준으로 해당 요소들의 위치를 판단하고 .parallax__nav li 요소 중에서 활성화된 클래스인 active를 제거하고, 현재 스크롤 위치를 기준으로 활성화될 요소를 결정합니다. 그리고 document.querySelector(".parallax__nav li:nth-child("+(index+1)+")").classList.add("active"); 코드에서는 결정된 활성화될 요소에 active 클래스를 추가합니다.
document.querySelectorAll(".parallax__nav li a").forEach(li => {...} 부분에서는 .parallax__nav li 요소들에 이벤트를 바인딩합니다. 각각의 요소가 클릭되면 해당 요소의 href 속성 값을 이용하여 해당 위치로 스크롤 이동합니다.
마지막으로 document.querySelector(".scroll span").innerText = parseInt(scrollTop); 코드에서는 현재 스크롤 위치를 .scroll 요소 안에 있는 span 요소에 출력합니다.
주석 처리된 코드에서는 각각의 #section1, #section2, ..., #section9 요소의 위치를 출력하기 위한 코드가 포함되어 있습니다. 하지만 해당 부분은 주석 처리되어 있으므로 현재 코드에서는 동작하지 않습니다.
for문
for(i=1; i<10; i++){
document.querySelector(".info .offset"+i).innerText = document.getElementById("section"+i).offsetTop
}
for문을 이용하여 좌표값을 넣어주는 방법입니다.
i값에 1부터 시작하여 9까지 반복되게 만들며 .info .offset과 section에 반복되는 값인 i값을 더해 좌표값을 넣어줍니다.
forEach문
//forEach
document.querySelectorAll('.info li').forEach((el, i) => {
document.querySelector(".info .offset"+(i+1)).innerText = document.getElementById("section"+(i+1)).offsetTop;
});
for문을 forEach로 변경 해보았습니다.
인자 값이 0부터 시작되기에 (i+1)을 넣어서 1부터 차례대로 늘어나게 만들어 주었습니다.
for in문
//for in
for(let i in document.querySelectorAll(".info li")){
document.querySelector(".info .offset"+(parseInt(i)+1)).innerText = document.getElementById("section"+(parseInt(i)+1)).offsetTop;
}
for in문은 배열의 키값을 반환 하지만 숫자가 아니라 문자열을 반환 하기에 문자열을 숫자로 반환 해주는 parseInt를 이용하여 숫자로 반환 해줍니다.
for of문
//for of
for (const [i, el] of document.querySelectorAll(".info li span").entries()){
el.innerHTML = document.getElementById("section"+(parseInt(i)+1)).offsetTop;
}
for of문은 요소를 가져오기에 직접적으로 span태그를 추가로 입력 해주었습니다.
entries()는 객체를 배열 형태로 반환 해준다고 이해 하였습니다. 이걸 사용하여 배열의 키값을 구해줍니다.