패럴랙스 이펙트 5
이번 패럴랙스 효과는 스크롤이 내려가면 사진과 텍스트가 스크롤과 달리 움직이며 이질감을 주는 효과입니다. 이질감을 주는 방법을 알아볼까요?
HTML 코드
이번 패럴랙스는 메뉴 없이 컨텐츠로만 구성하였으며, scrollTop 정보를 볼 수 있는 info를 추가해주었습니다.
HTML 보기
<main id="parallax__cont">
<div id="contents">
<section id="section01" class="content__item">
<span class="content__item__num">01</span>
<h2 class="content__item__title">section1</h2>
<figure class="content__item__imgWrap">
<div class="content__item__img"></div>
</figure>
<p class="content__item__desc">질병은 입을 쫓아 들어가고 화근은 입을 좇아 나온다.</p>
</section>
<!-- //section01 -->
.
.
.
</div>
</main>
<!-- main -->
<aside id="parallax__info">
<div class="scroll">scrollTop : <span>0</span>px</div>
</aside>
<!-- info -->
CSS 코드
이번 패럴랙스는 gsap를 활용하여 애니메이션을 주었기 때문에, 트랜지션 속성은 주석처리 해주었습니다.
CSS 보기
/* parallax__cont */
#parallax__cont {
max-width: 1600px;
width: 98%;
margin: 0 auto;
/* background-color: rgba(255,255,255,0.1); */
}
.content__item {
width: 1000px;
max-width: 70vw;
margin: 30vw auto;
/* background-color: rgba(255,255,255,0.3); */
text-align: left;
margin-right: 0;
position: relative;
padding-top: 9vw;
}
.content__item:nth-child(even) { /* 2n: n은 변수, even: 짝수만 선택 */
margin-left: 0;
text-align: right;
}
.content__item:nth-child(even) .content__item__num {
left: auto; /*left 값 초기화 */
right: -5vw;
}
.content__item__num {
font-size: 35vw;
font-family: 'Lato';
font-weight: 100;
position: absolute;
left: -5vw;
top: -13vw;
opacity: 0.07;
z-index: -2;
}
.content__item__title {
font-weight: 400;
text-transform: capitalize; /* 첫글자만 대문자 */
}
.content__item__imgWrap {
width: 100%;
padding-bottom: 56.25%;
background-color: #000;
position: relative;
overflow: hidden;
z-index: -1;
}
.content__item__img {
position: absolute;
background-image: url(../assets/img/effect_img10-min.jpg);
background-repeat: no-repeat;
background-position: center center;
width: 110%;
background-size: cover;
height: 110%;
left: -5%;
top: -5%;
filter: saturate(0%);
/* transition: all 1s; */
}
.content__item:nth-child(1) .content__item__img {
background-image: url(../assets/img/effect_img10-min.jpg);
}
.content__item:nth-child(2) .content__item__img {
background-image: url(../assets/img/effect_img09-min.jpg);
}
.content__item:nth-child(3) .content__item__img {
background-image: url(../assets/img/effect_img08-min.jpg);
}
.content__item:nth-child(4) .content__item__img {
background-image: url(../assets/img/effect_img07-min.jpg);
}
.content__item:nth-child(5) .content__item__img {
background-image: url(../assets/img/effect_img06-min.jpg);
}
.content__item:nth-child(6) .content__item__img {
background-image: url(../assets/img/effect_img05-min.jpg);
}
.content__item:nth-child(7) .content__item__img {
background-image: url(../assets/img/effect_img04-min.jpg);
}
.content__item:nth-child(8) .content__item__img {
background-image: url(../assets/img/effect_img03-min.jpg);
}
.content__item:nth-child(9) .content__item__img {
background-image: url(../assets/img/effect_img02-min.jpg);
}
.content__item__desc {
font-size: 4vw;
line-height: 1.4;
margin-top: -5vw;
margin-left: -4vw;
word-break: keep-all;
}
.content__item:nth-child(even) .content__item__desc {
margin-left: auto;
margin-right: -4vw;
}
@media(max-width: 800px) {
#parallax__cont {
margin-top: 70vw;
}
}
#parallax__info {
position: fixed;
left: 20px;
bottom: 20px;
z-index: 2000;
background-color: rgba(0,0,0,0.6);
color: #fff;
padding: 15px 20px;
border-radius: 10px;
}
스크립트 요약
1. 스크롤 값을 구해, 스크롤이 내려감에 따라 이미지나 텍스트가 같이 움직이도록 합니다.
2. 구한 스크롤 값을 info에 나타냅니다.
3. 각각의 컨텐츠 구성요소가 스크롤 할 때 같이 움직이도록 합니다.
4. 스크롤 이벤트가 발생하면 해당 함수가 실행되도록 합니다.
전체 스크립트 보기
function scroll(){
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
document.querySelector("#parallax__info span").innerText = Math.ceil(scrollTop);
document.querySelectorAll(".content__item").forEach(item => {
const target1 = item.querySelector(".content__item__img");
const target2 = item.querySelector(".content__item__desc");
const target3 = item.querySelector(".content__item__num");
let offset1 = (scrollTop - item.offsetTop) * 0.1;
let offset2 = (scrollTop - item.offsetTop) * 0.15;
let offset3 = (scrollTop - item.offsetTop) * 0.2;
// target1.style.transform = `translateY(${offset1}px)`;
// target2.style.transform = `translateX(${offset2}px)`;
gsap.to(target1, {duration: .3, y: offset1, ease: "power4.out"});
gsap.to(target2, {duration: .3, y: offset2});
gsap.to(target3, {duration: .3, y: offset3, ease: "expo.out"});
});
requestAnimationFrame(scroll);
}
scroll();
스크립트 뜯어보기
스크립트를 차근차근 뜯어보며 이해해 봅시다!
> 함수 작성하기
: scroll이라는 함수를 작성하고 실행문도 함께 작성해 줍니다. 이 함수는 스크롤 이벤트가 발생할 때마다 실행시킬 예정입니다.
function scroll(){};
scroll();
> scroll 함수 실행문 작성 01
: scrollTop 변수를 만들어 스크롤 값을 구해 저장해 줍니다. 이번에는 간단히 두개만 저장해 주었습니다.
⇒ 특정 브라우저에서 호환성의 문제로 앞의 값을 불러오지 못할 때, 대안으로 뒤의 값을 불러오기 위함입니다.
let scrollTop = window.pageYOffset || document.documentElement.scrollTop;
> scroll 함수 실행문 작성 02
: scrollTop 값을 보여줄 info 요소의 글씨가 들어가는 부분을 선택하고, innerText를 이용해 scrollTop 값을 넣어줍니다.
⇒ 소수점까지 보이지 많도록 값을 올림하여 줍니다.
document.querySelector("#parallax__info span").innerText = Math.ceil(scrollTop);
> scroll 함수 실행문 작성 03
: 모든 컨텐츠 요소를 선택하여, forEach문을 통해 스크롤 이벤트가 발생할 때마다 각 요소가 같이 움직이는 애니메이션이 실행되도록 합니다.
item?
⇒ ForEach의 대상인 .content__item들 각각의 요소를 의미합니다.(section01, section002, …)
target1~3 ?
⇒ 각각 해당 섹션의 이미지, 텍스트, 번호 요소를 선택합니다.
offset1~3 ?
⇒ 만약 섹션의 크기가 window의 크기와 정확히 일치한다면, (scrollTop - item.offsetTop)의 값은 0이 됩니다. 그러나 그런 경우는 거의 없기 때문에 어떤 값이 나타나게 되고, 그 값에 0.1 등을 곱하게 되면 스크롤이 100만큼 움직일 때 요소는 1만큼 움직이게 되며 이질감을 주게 됩니다. 곱한 값이 클수록 빨리(많이) 움직이게 됩니다.
gsap.to(~) ?
⇒ gsap.to(대상 요소, {애니메이션 속성});
- duration : 지속시간
- y : y축으로 이동
- ease : 전환 효과
document.querySelectorAll(".content__item").forEach(item => {
const target1 = item.querySelector(".content__item__img");
const target2 = item.querySelector(".content__item__desc");
const target3 = item.querySelector(".content__item__num");
let offset1 = (scrollTop - item.offsetTop) * 0.1;
let offset2 = (scrollTop - item.offsetTop) * 0.15;
let offset3 = (scrollTop - item.offsetTop) * 0.2;
// target1.style.transform = `translateY(${offset1}px)`;
// target2.style.transform = `translateX(${offset2}px)`;
gsap.to(target1, {duration: .3, y: offset1, ease: "power4.out"});
gsap.to(target2, {duration: .3, y: offset2});
gsap.to(target3, {duration: .3, y: offset3, ease: "expo.out"});
});
> scroll 함수 실행문 작성 04
: requestAnimationFrame() 메서드를 이용해, 스크롤 이벤트가 발생하면 scroll 함수를 실행하도록 합니다.
⇒ requestAnimationFrame() 메서드는 addEventListener()의 scroll과 같이 스크롤 이벤트를 발생시키는 메서드입니다. 그러나, 브라우저에 최적화 되어 있기 때문에 addEventListener()보다 훨씬 부드럽고 가볍다는 장점이 있습니다.
⇒ 이 스크립트의 경우처럼, 어떤 함수 안에 그 함수 자신의 실행문이 존재하는 것을 재귀함수라고 합니다.
requestAnimationFrame(scroll);
> 완성 페이지 보기
'Effect > Parallax Effect' 카테고리의 다른 글
패럴랙스 이펙트07 (1) | 2022.10.20 |
---|---|
패럴랙스 이펙트06 (4) | 2022.09.29 |
패럴랙스 이펙트04 (2) | 2022.09.18 |
패럴랙스 이펙트03 (7) | 2022.09.10 |
패럴랙스 이펙트02 (3) | 2022.09.10 |
댓글