GSAP 패럴랙스 이펙트
소개
안녕하세요! 웹스토리보이입니다. GSAP Parallax Effect Pin 애니메이션에 대해서 배워보겠습니다. scrollTrigger
속성 중에 pin 애니메이션 기억하시죠? 무엇인가를 고정시킬 때 사용하는 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;
}
#section2,
#section4,
#section6,
#section8 {
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;
margin: 1vw;
background-color: #fff;
background-size: cover;
background-position: center;
}
#section1 .parallax__item__img {
background-image: url(assets/img/images14.jpg);
}
#section2 .parallax__item__img {
background-image: url(assets/img/images15.jpg);
}
#section3 .parallax__item__img {
background-image: url(assets/img/images03.jpg);
}
#section4 .parallax__item__img {
background-image: url(assets/img/images04.jpg);
}
#section5 .parallax__item__img {
background-image: url(assets/img/images05.jpg);
}
#section6 .parallax__item__img {
background-image: url(assets/img/images06.jpg);
}
#section7 .parallax__item__img {
background-image: url(assets/img/images07.jpg);
}
#section8 .parallax__item__img {
background-image: url(assets/img/images08.jpg);
}
#section9 .parallax__item__img {
background-image: url(assets/img/images09.jpg);
}
/* option */
#section3 .parallax__item__img {
width: 100px;
height: 100px;
border-radius: 50px;
}
#section5 {
flex-direction: column;
}
#section5 .parallax__item__text,
#section6 .parallax__item__text {
font-size: 5vw;
text-transform: uppercase;
font-weight: bold;
}
#section7 .parallax__item__text {
font-size: 5vw;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background-color: #111;
padding: 30px;
width: 100%;
text-align: center;
}
#section8 {
flex-direction: column;
}
#section8 .parallax__item__text {
font-size: 2vw;
line-height: 1.5;
text-transform: uppercase;
}
#section8 .parallax__item__img {
width: 100px;
height: 100px;
border-radius: 50%;
}
#section9 .parallax__item__img {
width: 200px;
height: 200px;
border-radius: 50%;
}
</style>
</head>
<body>
<header id="parallax__title">
<h1>GSAP Parallax Effect02</h1>
<p>GSAP scrollTrigger - Pin 애니메이션</p>
<ul>
<li><a href="gsap01.html">1</a></li>
<li class="active"><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 i1"></div>
<div class="parallax__item__img i2"></div>
<div class="parallax__item__img i3"></div>
</section>
<!-- //section2 -->
<section id="section3" class="parallax__item">
<span class="parallax__item__num">03</span>
<div class="parallax__item__img"></div>
<div class="parallax__item__img"></div>
<div class="parallax__item__img"></div>
<div class="parallax__item__img"></div>
<div class="parallax__item__img"></div>
<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__text t1">section5</div>
<div class="parallax__item__text t2">section5</div>
<div class="parallax__item__text t3">section5</div>
<div class="parallax__item__text t4">section5</div>
</section>
<!-- //section5 -->
<section id="section6" class="parallax__item">
<span class="parallax__item__num">06</span>
<div class="parallax__item__text">section6</div>
</section>
<!-- //section6 -->
<section id="section7" class="parallax__item">
<span class="parallax__item__num">07</span>
<div class="parallax__item__text t1">코딩이란</div>
<div class="parallax__item__text t2">프로그래밍 코드를</div>
<div class="parallax__item__text t3">어딘가에</div>
<div class="parallax__item__text t4">적는 것을 말한다</div>
<div class="parallax__item__text t5">코딩은</div>
<div class="parallax__item__text t6">누구나</div>
<div class="parallax__item__text t7">할 수 있다.</div>
</section>
<!-- //section7 -->
<section id="section8" class="parallax__item">
<span class="parallax__item__num">08</span>
<div class="parallax__item__text t1">section8 title1</div>
<div class="parallax__item__text t2">section8 title2</div>
<div class="parallax__item__text t3">section8 title3</div>
<div class="parallax__item__img i1"></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>
<script>
</script>
</body>
</html>
2. 스크립트 작업하기
2-1. 기본 애니메이션
pin
속성을 이용해서 고정을 시키고 애니메이션을 주는 기법입니다. 패럴랙스에 많이 사용하는 방법 중에 하나입니다. 이번에 스크롤 트리거는 ScrollTrigger.create
를 이용해서 작업하겠습니다. 예제 1번에 사용했던 방법과 동일합니다. 단지 방법의 차이가 있을 뿐입니다. 둘다 많이 사용하기 때문에 둘다 사용하는 방법을 알고 있어야 합니다. anticipatePin
속성은 핀 효과를 조금 더 자연스럽게 연출하기 위한 속성입니다. 아래 소스와 같이 작성하면 이미지는 회전을 하면서 작아지고 커지는 효과를 연출하였습니다.
// 01 : 이미지 애니메이션 주기
const ani1 = gsap.timeline();
ani1.to("#section1 .parallax__item__img", {rotation: 720, scale: 0, borderRadius: 200})
.to("#section1 .parallax__item__img", {rotation: 0, scale: 1, borderRadius: 20})
ScrollTrigger.create({
animation: ani1,
trigger: "#section1",
start: "top top",
end: "+=2000",
scrub: true,
pin: true,
anticipatePin: 1,
markers: false
});
2-2. 이미지 순차적으로 나오기
이번에는 이미지를 순차적으로 나오게 작업하였습니다. 두번째 섹션이 되면 화면은 고정되고 이미지가 하나씩 나옵니다. from
메서드는 to
메서드의 반대라고 생각하면 됩니다. 현재 y
의 값은 0이기 때문에 애니메이션을 -100에서 0으로 준다고 생각하면 됩니다. end: "+=2000"
속성은 요소가 끝나는 부분부터 2000px을 더 준다고 생각하면 끝나는 점이 더 멀어지기 때문에 속도 조절이나 길이 조정이 가능합니다.
// 02 : 이미지 순차적으로 나오기
const ani2 = gsap.timeline();
ani2.from("#section2 .i1", {y: -100, autoAlpha:0, borderRadius: 200})
.from("#section2 .i2", {y: 100, autoAlpha:0, borderRadius: 200})
.from("#section2 .i3", {y: -100, autoAlpha:0, borderRadius: 200});
ScrollTrigger.create({
animation: ani2,
trigger: "#section2",
start: "top top",
end: "+=2000",
scrub: true,
pin: true,
anticipatePin: 1,
markers: false
});
2-3. 이미지 랜덤으로 떨어지기
gsap.timeline()
메서드를 주면 요소에 순차적으로 애니메이션을 줄 수 있습니다. 변수에 저장을 하고 해당 요소에 애니메이션을 주면 편합니다. 이번에는 이미지가 랜덤으로 나오게 설정했습니다. autoAlpha
는 투명도를 설정하고 y
값은 transform: translateY를 말합니다. ease
효과는 움직이는 효과를 말하고 stagger
는 이미지들을 말합니다. 이미지가 여러개 있기 때문에 순차적으로 random
을 설정할 수 있습니다. 이렇게 하면 스크롤 할 때마다 랜덤으로 이미지를 연출할 수 있습니다.
// 03 : 이미지 랜덤으로 떨어지기
const ani3 = gsap.timeline();
ani3.from("#section3 .parallax__item__img", {
autoAlpha: 0,
y: -100,
ease: "back.out(4)",
stagger: {
amount: 3,
from: "random"
}
})
ScrollTrigger.create({
animation: ani3,
trigger: "#section3",
start: "top top",
end: "+=3000",
scrub: true,
pin: true,
markers: false,
anticipatePin: 1
});
2-4. 이미지 축소하기
이미지를 화면에 맞게 width: "100vw"
, height: "100vh"
설정 후, 지금 크기 값으로 애니메이션 할 수 있도록 from
메서드를 사용하였습니다. 투명도는 0에서 1로 설정하였습니다. 이렇게 하면 전체 이미지가 축소되면서 애니메이션이 연출됩니다. 이 효과도 많이 사용하는 효과입니다.
// 04 : 이미지 축소하기
const ani4 = gsap.timeline();
ani4.from("#section4 .parallax__item__img", {
autoAlpha:0,
scale: 5,
width: "100vw",
height: "100vh"
})
ScrollTrigger.create({
animation: ani4,
trigger: "#section4",
start: "top top",
end: "+=3000",
scrub: true,
pin: true,
markers: false,
anticipatePin: 1
});
2-5. 텍스트 애니메이션
이번에는 텍스트를 이용해서 작업해보겠습니다. 4개의 텍스트를 만들고 x축으로 300%를 설정했습니다. 퍼센트를 표현할 때에는 xPercent
라고 설정합니다. 4개의 요소가 동시에 움직이고 싶다면, 아래와 같이 "text"
문자열을 추가하면 됩니다. 문자열 이름은 랜덤입니다.
// 05 : 텍스트 애니메이션
const ani5 = gsap.timeline();
ani5.to("#section5 .t1", {xPercent: 300}, "text")
.to("#section5 .t2", {xPercent: -300}, "text")
.to("#section5 .t3", {xPercent: 300}, "text")
.to("#section5 .t4", {xPercent: -300}, "text")
ScrollTrigger.create({
animation: ani5,
trigger: "#section5",
start: "top top",
end: "+=3000",
scrub: true,
pin: true,
markers: true,
anticipatePin: 1
});
2-6. 텍스트 확대하기
이미지처럼 텍스트 역시 확대하거나 축소가 가능합니다. 텍스트를 이용해서 확대하면서 화면을 전환하는 효과를 많이 사용합니다. scale
를 이용하여 60배 정도 확대하고 투명도를 0으로 설정했습니다.
// 06 : 텍스트 확대하기
const ani6 = gsap.timeline();
ani6.to("#section6 .parallax__item__text", {scale: 60, duration: 2, autoAlpha: 1})
.to("#section6 .parallax__item__text", {autoAlpha: 0})
ScrollTrigger.create({
animation: ani6,
trigger: "#section6",
start: "top top",
end: "+=4000",
scrub: true,
pin: true,
anticipatePin: 1,
markers: false
});
2-7. 텍스트 제자리 애니메이션
테스트를 이용하여 제자리애서 변경하는 애니메이션을 구현했습니다. 처음에는 투명도를 0으로 설정하고 밑에서 위로 나오도록 설정했습니다. 텍스트 하나가 끝나고 바로 다음 텍스트가 나오기 때문에 "+=1"
을 추가하여 조금 더 자연스럽게 나오도록 했습니다.
// 07 : 텍스트 제자리 애니메이션
const ani7 = gsap.timeline();
ani7.from("#section7 .t1", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t2", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t3", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t4", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t5", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t6", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
.from("#section7 .t7", {autoAlpha: 0, duration: 1, y: 50}, "+=1")
ScrollTrigger.create({
animation: ani7,
trigger: "#section7",
start: "top top",
end: "+=6000",
scrub: true,
pin: true,
markers: false,
anticipatePin: 1
});
2-8. 텍스트 애니메이션
이번에는 텍스트를 자연스럽게 나오도록 설정했습니다. 현재 x
의 값이 가운데로 설정되어 있기 때문에 from
를 이용해서 화면 밖에 왼쪽, 오른쪽에 나올 수 있도록 innerWidth
을 설정했습니다. -1
을 설정하면 반대로 나오겠죠!
// 08 : 텍스트 애니메이션
const ani8 = gsap.timeline();
ani8.from("#section8 .t1", {x: innerWidth * 1})
.from("#section8 .t2", {x: innerWidth * -1})
.from("#section8 .t3", {x: innerWidth * 1})
.from("#section8 .i1", {x: innerWidth * 1, rotation: 360, scale: 1.5})
ScrollTrigger.create({
animation: ani8,
trigger: "#section8",
start: "top top",
end: "+=4000",
scrub: true,
pin: true,
markers: false,
anticipatePin: 1
});
2-9. 텍스트 애니메이션
마지막으로 이미지를 확대해서 없어지는 걸로 마무리했습니다. 이미지가 커진 다음 투명도를 0으로 설정했습니다.
//09 : 이미지 확대하기
const ani9 = gsap.timeline();
ani9.to("#section9 .parallax__item__img", {scale: 13})
.to("#section9 .parallax__item__img", {autoAlpha: 0})
ScrollTrigger.create({
animation: ani9,
trigger: "#section9",
start: "top top",
end: "+=4000",
scrub: true,
pin: true,
markers: false,
anticipatePin: 1
});
3. 마무리
예제 1번의 애니메이션 기본과 예제 2번의 핀 애니메이션을 이용하면 패럴랙스의 대부분 효과를 연출할 수 있습니다. 기본기를 배웠으니 이제는 여러분들이 응용해서 더 멋있는 효과를 만들 차례입니다. 그 전에 조금더 다양한 효과를 더 배우고 멋있는 사이트를 만들어 보도록 합시다. 수고하셨습니다. 🥺
예제 목록
- 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 패럴랙스 이펙트 : 스무스 효과
댓글