완성 화면
코드 보기 / CSS
.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%;
z-index: 1;
background-color: cornflowerblue;
}
/* before animation (1개)*/
.reveal.show::before {
animation: reveal 1s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-RTL.show::before {
animation: reveal-RTL 1s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-TTB.show::before {
animation: reveal-TTB 1s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-BTT.show::before {
animation: reveal-BTT 1s cubic-bezier(0, 0.78, 0.58, 1);
}
/*before,after (2개) */
.reveal.show::after {
animation: reveal 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-RTL.show::after {
animation: reveal-RTL 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-TTB.show::after {
animation: reveal-TTB 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
}
.reveal.reveal-BTT.show::after {
animation: reveal-BTT 1s 0.5s cubic-bezier(0, 0.78, 0.58, 1);
}
/* 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-BTT {
0% {width: 100%; height: 0; bottom:0; top: auto;}
50% {width: 100%; height: 100%; bottom:0; top: auto;}
80% {width: 100%; height: 100%; bottom:0; top: auto;}
100% {width: 100%; height: 0; bottom:100%; top: auto;}
}
.parallax__item__num,
.parallax__item__title {
display: none;
}
코드 보기 / HTML
<div class="parallax__wrap">
<section id="section1" class="parallax__item">
<span class="parallax__item__num">01</span>
<h2 class="parallax__item__title">Section 01</h2>
<figure class="parallax__item__imgWrap">
<div class="parallax__item__img"></div>
</figure>
<p class="parallax__item__desc split">좋은 책은 우리에게 생각하는 법을 가르쳐준다.</p>
</section>
<!--//section 01-->
코드 보기 / JAVASCRIPT
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
<script>
//reveal class 추가 시 -> 자식 요소를 span으로 감싼다.
document.querySelectorAll("p.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/2) {
// reveal.classList.add("show");
// }
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();
document.querySelectorAll("p.reveal").forEach(text => { ... })
: 문서에서 CSS 선택자 p.reveal에 해당하는 모든 요소를 선택하고 각 요소에 대해 반복문을 실행합니다. 선택된 요소들은 "reveal" 클래스를 가지고 있는 p 요소들입니다.
text.innerHTML = <span>${text.innerHTML}</span>;
: 선택된 p.reveal 요소의 내용을 <span> 태그로 감싸서 변경합니다. 이를 통해 텍스트를 자식 요소로 갖는 <span> 태그가 추가됩니다.
function scroll() { ... }
: scroll 함수를 정의합니다. 이 함수는 스크롤 이벤트를 처리하고, 요소의 나타남을 관리합니다.
let scrollTop = window.scrollY || window.pageYOffset;
: scrollTop 변수를 선언하고, 현재 스크롤 위치를 저장합니다. window.scrollY 또는 window.pageYOffset 속성을 사용하여 스크롤 위치를 가져옵니다.
const reveals = document.querySelectorAll(".reveal");
: 문서에서 CSS 선택자 .reveal에 해당하는 모든 요소를 선택하여 reveals에 저장합니다. 선택된 요소들은 "reveal" 클래스를 가지고 있는 모든 요소입니다.
reveals.forEach(reveal => { ... })
: reveals에 포함된 각 요소에 대해 반복문을 실행합니다.
let revealOffset = reveal.offsetTop + reveal.parentElement.offsetTop;
: reveal 요소의 세로 위치를 계산하여 revealOffset 변수에 저장합니다. offsetTop 속성은 요소의 부모를 기준으로 한 상대적인 세로 위치를 반환합니다.
let revealDelay = reveal.dataset.delay;
: reveal 요소의 data-delay 속성 값을 가져와서 revealDelay 변수에 저장합니다. data-delay 속성은 요소가 나타나기까지의 지연 시간을 나타냅니다.
if(scrollTop >= revealOffset - window.innerHeight) { ... }
: 스크롤 위치가 revealOffset - window.innerHeight보다 크거나 같을 때 다음 조건을 확인합니다.
if(revealDelay == undefined) { ... } else { ... }
: revealDelay 변수가 정의되어 있는지 확인합니다. 만약 정의되어 있지 않다면 지연 없이 즉시 reveal 요소에 "show" 클래스를 추가합니다. 그렇지 않다면 setTimeout 함수를 사용하여 revealDelay 값만큼의 지연 후에 "show" 클래스를 추가합니다.
document.querySelector(".scroll span").innerText = Math.round(scrollTop);
: 문서에서 CSS 선택자 .scroll span에 해당하는 요소를 선택하고, 해당 요소의 내용을 현재 스크롤 위치인 scrollTop으로 변경합니다.
requestAnimationFrame(scroll);
: 스크롤 이벤트 처리를 위해 requestAnimationFrame 함수를 호출하여 scroll 함수를 반복적으로 실행합니다. 이를 통해 부드러운 스크롤 이벤트 처리가 가능해집니다.