GSAP 패럴랙스 이펙트 : 배경 고정하기
소개
안녕하세요! 웹스토리보이입니다. pin 속성을 이용하여 배경을 고정하는 효과를 배워보겠습니다. 스크롤을 내리면 배경이 고정되어 있고, 다음 섹션이 올라오는 형태의 애니메이션입니다.
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;
flex-direction: column;
}
#section2,
#section4,
#section6,
#section8 {
background-color: #222;
}
.parallax__item__num {
position: absolute;
right: 20px;
bottom: 20px;
font-size: 3vw;
line-height: 1;
z-index: 10;
}
.parallax__item__img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100vh;
background-color: #fff;
background-size: cover;
background-position: center;
}
.parallax__item__img::after {
content: '';
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100vh;
background-color: rgba(0,0,0,0.7);
z-index: 1;
}
#section1 .parallax__item__img {
background-image: url(assets/img/images02@2.jpg);
}
#section2 .parallax__item__img {
background-image: url(assets/img/images03@2.jpg);
}
#section3 .parallax__item__img {
background-image: url(assets/img/images04@2.jpg);
}
#section4 .parallax__item__img {
background-image: url(assets/img/images05@2.jpg);
}
#section5 .parallax__item__img {
background-image: url(assets/img/images06@2.jpg);
}
#section6 .parallax__item__img {
background-image: url(assets/img/images07@2.jpg);
}
#section7 .parallax__item__img {
background-image: url(assets/img/images08@2.jpg);
}
#section8 .parallax__item__img {
background-image: url(assets/img/images09@2.jpg);
}
#section9 .parallax__item__img {
background-image: url(assets/img/images10@2.jpg);
}
.parallax__item__title {
font-size: 5vw;
z-index: 100;
text-transform: uppercase;
display: inline-block;
}
</style>
</head>
<body>
<header id="parallax__title">
<h1>GSAP Parallax Effect03</h1>
<p>GSAP scrollTrigger - 배경 고정하기</p>
<ul>
<li><a href="gsap01.html">1</a></li>
<li><a href="gsap02.html">2</a></li>
<li class="active"><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>
<h2 class="parallax__item__title">section1</h2>
</section>
<!-- //section1 -->
<section id="section2" class="parallax__item">
<span class="parallax__item__num">02</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section2</h2>
</section>
<!-- //section2 -->
<section id="section3" class="parallax__item">
<span class="parallax__item__num">03</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section3</h2>
</section>
<!-- //section3 -->
<section id="section4" class="parallax__item">
<span class="parallax__item__num">04</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section4</h2>
</section>
<!-- //section4 -->
<section id="section5" class="parallax__item">
<span class="parallax__item__num">05</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section5</h2>
</section>
<!-- //section5 -->
<section id="section6" class="parallax__item">
<span class="parallax__item__num">06</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section6</h2>
</section>
<!-- //section6 -->
<section id="section7" class="parallax__item">
<span class="parallax__item__num">07</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section7</h2>
</section>
<!-- //section7 -->
<section id="section8" class="parallax__item">
<span class="parallax__item__num">08</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section8</h2>
</section>
<!-- //section8 -->
<section id="section9" class="parallax__item">
<span class="parallax__item__num">09</span>
<div class="parallax__item__img"></div>
<h2 class="parallax__item__title">section9</h2>
</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>
<script>
</script>
</body>
</html>
2. 스크립트 작업하기
2-1. 한개 섹션 고정시키기
현재는 9개의 섹션으로 구성되어 있습니다. 첫 번째 섹션만 고정을 시켜보도록 하겠습니다. 고정 시킬 패널을 변수에 저장하고, ScrollTrigger.create
를 설정합니다. 트리거는 자기 자신으로 설정하고 pin: true
를 설정합니다. 핀을 설정하면 밑에 여백이 생길 수 있는 이 부분을 제거해 주려면 pinSpacing: false
로 설정합니다.
const panel = document.querySelector("#section1");
ScrollTrigger.create({
trigger: panel,
start: "top top",
pin: true,
pinSpacing: false
});
2-2. 여러개 섹션 고정시키기
이번에는 9개의 섹션의 다 적용해보겠습니다. GSAP에서는 다중 선택을 할 때에는 gsap.utils.toArray
를 사용합니다. 모든 섹션의 공통 요소 parallax__item
을 선택한 후 자바스크립트 forEach
를 사용하면 됩니다. 나머지는 위 예제와 동일합니다.
gsap.utils.toArray(".parallax__item").forEach((panel, i) => {
ScrollTrigger.create({
trigger: panel,
start: "top top",
pin: true,
pinSpacing: false
});
});
2-3. 스냅 고정 효과 만들기
이번에는 스냅 효과를 적용하여 배경을 고정할 수 있습니다. 스크롤을 했는데 다음 섹션이 위쪽에 가까운면 위쪽으로 붙여주고, 아래쪽에 가까우면 아래쪽에 붙여주는 효과입니다. 좀 더 고급스러운 효과라고 할 수 있습니다. 그래서 소스도 조금 더 복잡합니다. forEach
와 비슷한 map
메서드를 사용하여 tops
변수에 trigger와 start를 저장했습니다. 모든 패널에 스타트를 설정했는데 섹션의 offsetHeight
와 브라우저의 innerHeight
를 비교하여 시작점을 위로 할지 아래로 할지 정하는 소스를 설정했습니다. 그리고 스냅을 설정하기 위해 snapTo
를 설정하여, 스냅의 위치를 설정하였습니다. 아까 만들어 놓은 tops
변수에 start 값을 다시 설정하고, self.scroll()
를 통해 움직임을 감지합니다. gsap.utils.normalize
는 값의 범위를 특정 최소값과 최대값 사이로 조정하여 일관된 비율로 변환하는 메서드입니다.
let panels = gsap.utils.toArray(".parallax__item");
let tops = panels.map(panel => ScrollTrigger.create({trigger: panel, start: "top top"}));
panels.forEach((panel, i) => {
ScrollTrigger.create({
trigger: panel,
start: () => panel.offsetHeight < window.innerHeight ? "top top" : "bottom bottom",
pin: true,
pinSpacing: false
});
});
ScrollTrigger.create({
snap: {
snapTo: (progress, self) => {
let panelStarts = tops.map(st => st.start),
snapScroll = gsap.utils.snap(panelStarts, self.scroll());
return gsap.utils.normalize(0, ScrollTrigger.maxScroll(window), snapScroll);
},
duration: 0.5
}
});
3. 마무리
수고하셨습니다. 배경 고정 효과를 3가지 스타일로 만들어 봤습니다. 한가지만 적용하고 싶은 경우, 다중 선택을 통해 적용하는 방법 등을 배웠습니다. 이 예제를 통해 forEach
와 map
메서드의 차이점과 개념을 알고 계셔야 합니다. 많이 사용하니까 이해가 안되면 먼저 외우세요! 그럼 또 이해가 갑니다. 수고하셨습니다.
예제 목록
- 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 패럴랙스 이펙트 : 스무스 효과
댓글