GSAP 패럴랙스 이펙트
소개
안녕하세요! 웹스토리보이입니다. 이번에는 포트폴리오 스킬을 올릴 수 있는 방법에 대해서 공부해보겠습니다. 현재 오픈되어 있는 사이트들은 패럴랙스 형태의 사이트가 많습니다. 즉 스크롤을 내리면 무엇인가 움직이는 효과들이 많습니다. 이런 효과를 패럴랙스 효과라고 합니다. 패럴랙스 파트는 자바스크립트 파트와 GSAP 파트로 나눌 수 있습니다. 기본적인 사항은 자바스크립트를 통해 익히고, 퀄리티 있는 효과들을 GSAP를 통해서 작업할 것입니다. GSAP의 scrollTrigger를 이용하면, 퀄리티 있는 효과들을 만들 수 있습니다. 그럼 같이 한번 시작해볼까요? 🥹
1. 기본 구조 만들기
1-1. 준비하기
GSAP를 배우는 시간이기 때문에 HTML/CSS 코딩은 생략하겠습니다. 기본 코딩은 복사해서 사용하겠습니다. 우선 웹폰트를 설정하고 GSAP에서 필요한 파일을 미리 셋팅해 놓겠습니다. GSAP는 자주 업데이트가 되기 때문에 제일 최선 버전을 사용하는게 좋습니다.
<!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>GSAP Scroll Effect</title>
<!-- 웹폰트 설정 -->
<link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
</head>
<body>
<!-- GSAP 라이브러리 설정 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
</body>
</html>
1-2. 기본 셋팅하기
그대로 복사해서 사용해도 무방합니다.
<!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>GSAP Scroll Effect</title>
<link href="https://webfontworld.github.io/NexonLv1Gothic/NexonLv1Gothic.css" rel="stylesheet">
<style>
* {
margin: 0;
padding: 0;
}
a {
color: #fff;
text-decoration: none;
}
body {
color: #fff;
font-family: "NexonLv1Gothic";
font-weight: 300;
background-color: #111;
}
#parallax__title {
position: fixed;
left: 20px;
top: 20px;
z-index: 1000;
}
#parallax__title h1 {
font-size: 30px;
border-bottom: 1px dashed #fff;
margin-bottom: 10px;
padding-bottom: 5px;
font-weight: 400;
display: inline-block;
}
#parallax__title p {
font-size: 16px;
}
#parallax__title ul {
margin-top: 10px;
}
#parallax__title li {
display: inline;
}
#parallax__title li a {
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px dashed #fff;
display: inline-block;
text-align: center;
line-height: 20px;
font-size: 12px;
}
#parallax__title li.active a {
background: #fff;
color: #000;
}
/* parallax__cont */
#parallax__cont {
overflow: hidden;
}
.parallax__item {
width: 100%;
height: 100vh;
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
.parallax__item:nth-child(2n){
background-color: #222;
}
.parallax__item__num {
position: absolute;
right: 20px;
bottom: 20px;
font-size: 5vw;
line-height: 1;
}
.parallax__item__img {
width: 10vw;
height: 10vw;
background-color: #fff;
background-size: cover;
background-position: center;
}
.parallax__item:nth-child(1) .parallax__item__img {
background-image: url(assets/img/images14.jpg);
}
.parallax__item:nth-child(2) .parallax__item__img {
background-image: url(assets/img/images15.jpg);
}
.parallax__item:nth-child(3) .parallax__item__img {
background-image: url(assets/img/images03.jpg);
}
.parallax__item:nth-child(4) .parallax__item__img {
background-image: url(assets/img/images04.jpg);
}
.parallax__item:nth-child(5) .parallax__item__img {
background-image: url(assets/img/images05.jpg);
}
.parallax__item:nth-child(6) .parallax__item__img {
background-image: url(assets/img/images06.jpg);
}
.parallax__item:nth-child(7) .parallax__item__img {
background-image: url(assets/img/images07.jpg);
}
.parallax__item:nth-child(8) .parallax__item__img {
background-image: url(assets/img/images08.jpg);
}
.parallax__item:nth-child(9) .parallax__item__img {
background-image: url(assets/img/images09.jpg);
}
.parallax__item__img.active {
filter: hue-rotate(100deg);
}
</style>
</head>
<body>
<header id="parallax__title">
<h1>GSAP Parallax Effect01</h1>
<p>GSAP scrollTrigger - 애니메이션 기본 효과</p>
<ul>
<li class="active"><a href="gsap01.html">1</a></li>
<li><a href="gsap02.html">2</a></li>
<li><a href="gsap03.html">3</a></li>
<li><a href="gsap04.html">4</a></li>
<li><a href="gsap05.html">5</a></li>
<li><a href="gsap06.html">6</a></li>
<li><a href="gsap07.html">7</a></li>
<li><a href="gsap08.html">8</a></li>
<li><a href="gsap09.html">9</a></li>
<li><a href="gsap10.html">10</a></li>
<li><a href="gsap11.html">11</a></li>
<li><a href="gsap12.html">12</a></li>
<li><a href="gsap13.html">13</a></li>
<li><a href="gsap14.html">14</a></li>
<li><a href="gsap15.html">15</a></li>
</ul>
</header>
<!-- //parallax__title -->
<main id="parallax__cont">
<section id="section1" class="parallax__item">
<span class="parallax__item__num">01</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section1 -->
<section id="section2" class="parallax__item">
<span class="parallax__item__num">02</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section2 -->
<section id="section3" class="parallax__item">
<span class="parallax__item__num">03</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section3 -->
<section id="section4" class="parallax__item">
<span class="parallax__item__num">04</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section4 -->
<section id="section5" class="parallax__item">
<span class="parallax__item__num">05</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section5 -->
<section id="section6" class="parallax__item">
<span class="parallax__item__num">06</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section6 -->
<section id="section7" class="parallax__item">
<span class="parallax__item__num">07</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section7 -->
<section id="section8" class="parallax__item">
<span class="parallax__item__num">08</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section8 -->
<section id="section9" class="parallax__item">
<span class="parallax__item__num">09</span>
<div class="parallax__item__img"></div>
</section>
<!-- //section9 -->
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/gsap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.5/ScrollTrigger.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.1/ScrollToPlugin.min.js"></script>
</body>
</html>
2. 스크립트 작업하기
2-1. 기본 애니메이션
스크립트 태그를 설정하고 다음과 같이 작성합니다. 우선 선택자를 미리 만들어 놓겠습니다.
const box1 = document.querySelector("#section1 .parallax__item__img");
const box2 = document.querySelector("#section2 .parallax__item__img");
const box3 = document.querySelector("#section3 .parallax__item__img");
const box4 = document.querySelector("#section4 .parallax__item__img");
const box5 = document.querySelector("#section5 .parallax__item__img");
const box6 = document.querySelector("#section6 .parallax__item__img");
const box7 = document.querySelector("#section7 .parallax__item__img");
const box8 = document.querySelector("#section8 .parallax__item__img");
const box9 = document.querySelector("#section9 .parallax__item__img");
box1
요소를 2초동안 오른쪽으로 500px로 움직이겠습니다. 이렇게만 하면 심심하기 때문에 border-radius
를 주고 회전시키겠습니다. gsap의.to
메서드를 사용하면 선택한 요소는 움직입니다. gsap의 가장 기본 애니메이션입니다.
// 01
gsap.to(box1, {
duration: 2,
x: 500,
borderRadius: 100,
rotation: 360,
});
2-2. trigger
이번에는 스크롤을 내리고 요소가 보이는 영역에 오면 움직이도록 설정하겠습니다. 애니메이션 속성은 똑같이 작업을 하고 scrollTrigger
를 설정합니다. trigger
를 설정하면 스크롤을 내릴때 움직이기 시작합니다. 스크롤 이벤트를 작동시키기고 싶다면 scrollTrigger
속성을 설정하고, 움직이는 시점을 적용하기 위해서 trigger
를 설정하는 것입니다. 간단하죠? 내가 움직이는 시점 타겟을 설정하면 움직입니다.
// 02 : trigger
gsap.to(box2, {
duration: 2,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box2, //시작점 설정
}
});
2-3. toggleActions
이번에는 toggleActions
을 설정하겠습니다. 애니메이션의 행동을 설정하는 것입니다. 애니메이션이 시작했을 때, 애니메이션이 끝났을 때, 애니메이션이 시작하고 화면에 보이지 않을 때, 애니메이션이 끝나고 화면에 보이지 않을 때 4가지로 설정할 수 있습니다. onEnter
, onLeave
, onEnterBack
, onLeaveBack
를 의미하며, 여기에는 play
, pause
, resume
, reset
, restart
, complete
, reverse, none 요소 값을 설정할 수 있습니다. 하나씩 대입하면서 눈으로 직접확인하는 것이 가장 정확합니다.
// 03 : toggleActions
gsap.to(box3, {
duration: 1,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box3,
toggleActions: "play pause reverse none"
}
});
2-4. start, end
이번에는 애니메이션이 언제 시작하는지, 끝나는지를 설정하겠습니다. trigger
는 애니메이션의 기준점 역할을 하고, start
는 시작점을 의미합니다. start와 end는 두가지 요소 값을 설정합니다. 첫 번째 요소는 요소의 시작점을 의미하고, 두 번째 요소는 브라우저의 시작점을 의미합니다. 요소의 시작점과 브라우저의 시작점이 만나면 애니메이션이 작동되는 원리입니다. 여기에는 top
, bottom
, left
, right
, center
를 사용할 수 있으면, px
이나 %
사용도 가능합니다. 여기에서 markers: true
로 설정하면 마커의 위치를 확인할 수 있습니다.
// 04 : start, end
gsap.to(box4, {
duration: 1,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box4,
start: "top 50%",
end: "bottom 20%",
toggleActions: "play pause reverse pause",
markers: true,
}
});
2-5. scrub
이번에는 scrub
속성을 알아보겠습니다. 이 속성은 스크롤을 내리면 같이 움직이게 설정할 수 있습니다. 눈으로 직접 확인하는 것이 가장 정확합니다. 기본 scrollTrigger
를 설정하면, 시작점이 되었을 때 한번만 움직이지만, 이 효과는 마우스 스크롤 값에 따라 움직이도록 설정됩니다. 이 속성에는 true
및 정수 값을 넣을 수 있습니다. 미세한 차이가 있으니 직접 확인해보시면 좋을 거 같습니다.
// 05 : scrub
gsap.to(box5, {
duration: 1,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box5,
start: "top 50%",
end: "bottom 20%",
scrub: 0.5, //true, 1, 2,....
markers: false,
}
});
2-6. pin
pin
속성은 고정시키는 역할을 합니다. 패럴랙스 이펙트에서 많이 쓰이는 효과입니다. 알아두면 멋있는 사이트를 만들 수 있습니다. 고정시키는 역할은 다른 예제에서 더 자세히 다룹니다. 내가 위치한 영역에 고정시키기 위해서는 pin: true
를 설정합니다. 핀의 위치는 end
의 두번째 속성값을 변경해보면 확인할 수 있습니다.
// 06 : pin
gsap.to(box6, {
duration: 2,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box6,
start: "top 50%",
end: "top 100px",
pin: true,
scrub: true,
markers: true,
}
});
2-7. toggleClass
이번에는 toggleClass
속성을 설정해 보겠습니다. 시작점에 됐을 때 애니메이션도 줄 수 있지만 class
도 추가할 수 있습니다. 미리 CSS를 만들어 놓고 확인해보겠습니다. class
이름은 active
로 설정하였습니다. 여기에 id
값을 추가하면 마커의 이름을 변경할 수 있습니다.
// 07 : toggleClass
gsap.to(box7, {
duration: 2,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box7,
start: "top center",
end: "bottom top",
scrub: true,
markers: true,
toggleClass: "active",
id: "box7"
}
});
2-8. callback
이번에는 콜백함수에 대해서 알아보겠습니다. 콜백함수는 하나의 함수를 실행하고 그 다음 함수를 실행하는 함수라고 생각하면 됩니다. 보통은 두개의 함수를 실행시키면 동시에 실행되지만, 콜백함수는 하나의 함수가 실행되고, 끝나면 그 다음 함수가 실행되는 함수라고 생각하시면 이해하기가 편합니다. scrollTrigger
역시 여러가지 콜백함수를 제공하고 있습니다. toggleActions
처럼 onEnter
, onLeave
, onEnterBack
, onLeaveBack
메서드를 제공하며, onUpdate
이나 onToggle
같은 메서드도 제공합니다.
// 08 : callback
gsap.to(box8, {
duration: 2,
x: 500,
rotation: 360,
borderRadius: 100,
scrollTrigger: {
trigger: box8,
start: "top center",
end: "bottom 30%",
scrub: true,
markers: false,
// onEnter : () => {console.log("onEnter")},
// onLeave : () => {console.log("onLeave")},
// onEnterBack : () => {console.log("onEnterBack")},
// onLeaveBack : () => {console.log("onLeaveBack")},
// onUpdate : (self) => {console.log("onUpdate", self.progress.toFixed(3))},
onToggle : (self) => {console.log("onToggle", self.isActive)},
}
});
3. 마무리
이렇게 scrollTrigger
의 속성 값을 알아봤습니다. 이 밖에도 더 디테일한 기능들이 있지만, 기본적인 요소를 파악한 다음 하나씩 깊게 들어가보겠습니다. 기본적인 효과를 이해하고 스크롤 이벤트를 작업한다면 조금 더 수월하게 사이트를 만들 수 있습니다. 그럼 다음 예제에서 뵙겠습니다. 수고하셨습니다. 🤕
예제 목록
- 1. GSAP 패럴랙스 이펙트 : 기본 애니메이션
- 2. GSAP 패럴랙스 이펙트 : Pin 애니메이션
- 3. GSAP 패럴랙스 이펙트 : Pin 배경 고정하기
- 4. GSAP 패럴랙스 이펙트 : 이질감 효과
- 5. GSAP 패럴랙스 이펙트 : 나타나기 효과
- 6. GSAP 패럴랙스 이펙트 : 텍스트 효과
- 7. GSAP 패럴랙스 이펙트 : 배경색 효과
- 8. GSAP 패럴랙스 이펙트 : 진행바 효과
- 9. GSAP 패럴랙스 이펙트 : 메뉴 이동 효과
- 10. GSAP 패럴랙스 이펙트 : 메뉴 축소 효과
- 11. GSAP 패럴랙스 이펙트 : 메뉴 숨기기 효과
- 12. GSAP 패럴랙스 이펙트 : 가로 효과
- 13. GSAP 패럴랙스 이펙트 : 가로/세로 효과
- 14. GSAP 패럴랙스 이펙트 : 가로/세로 나타나기 효과
- 15. GSAP 패럴랙스 이펙트 : 스무스 효과
댓글