What I Learned Today
GSAP이란?
GreenSock Animation Platform의 약자로 웹 애니메이션을 위한 자바스크립트 라이브러리다.
먼저 GSAP를 사용하기 위해서는 HTML 파일에 라이브러리를 추가해야한다.
<script src="https://cdn.jsdelivr.net/npm/gsap@3.13.0/dist/gsap.min.js"></script>
GSAP은 CSS 속성, SVG, Canvas 등 거의 모든 것을 애니메이션 할 수 있다.
애니메이션을 만드는 방법
// 트윈 애니메이션 : 싱을 애니메이션을 말한다.
// 트윈 애니메이션의 메서드 (네 가지 유형)
gsap.to("target", vars) // 요소의 현재 상태에서 트윈에 정의된 값까지 애니메이션
gsap.from("target", vars) // 지정한 값에서 시작해 요소의 현재 상태로 애니메이션
gsap.fromTo("target", vars) // 시작값과 종료값을 모두 명확히 지정하여 애니메이션
gsap.set("target", vars) // 속성을 즉시 설정 (지속 시간 0의 .to()와 동일) - 애니메이션이 없다.
// 사용 예시
gsap.to(
'.circle',
{ x: 40, fill: 'green' },
)
gsap.from(
'.circle',
{ x: -40, fill: 'blue' },
)
gsap.fromTo(
'.circle',
{ x: -40, fill: 'blue' },
{ x: 40, fill: 'green' },
)
gsap.set(
'.circle',
{ x: 40, fill: 'blue' },
)
- GSAP 트윈에는 특별한 속성이 있다.
- duration : 애니메이션 지속 시간(초) - 기본값 : 0.5초
- delay : 애니메이션이 시작되기 전 지연 시간(초)
- repeat : 애니메이션이 반복되어야 하는 횟수
- yoyo : 값이 true일 경우 반복할 때마다 트윈이 반대 방향으로 실행 - 기본값 : false
- stagger : 여러 대상이 제공된 경우 각 대상의 애니메이션 시작 사이의 시간(초)
- ease : 애니메이션 중 변화율을 제어하며, 모션의 느낌과 같음 - 기본값 : power1.out
- onComplete : 애니메이션이 완료될 때 실행되는 함수
GSAP ease는 이징 과정 동안의 모멘텀(momentun, 탄력 또는 가속도)을 제어한다.
GSAP stagger는 트윈에 여러 대상이 있는 경우 각 애니메이션 시작 사이에 쉽게 지연 시간을 추가할 수 있다.
stagger를 사용하지 않는다면 delay 속성을 여러번 줘야하지만 stagger를 사용한다면 애니메이션 사이에 지연 시간을 줄 수 있다.
stagger는 다양한 옵션 값으로 더 많은 제어가 가능하다.
그런데 stagger를 사용하면 두개의 요소가 같이 애니메이션 되도록 하고싶은데 복잡할것이다.
그럴때에는 GSAP timeline이 있다.
GSAP timeline : 쉽게 조정 가능하고 탄력적인 애니메이션 시퀸스를 만드는 핵심으로 타임라인에 추가된 순서대로 재생이 된다.
// 타임라인 생성
const tl = gsap.timeline()
// 트윈을 타임라인에 추가
tl.to('.green', { x: 600, duration: 2 })
tl.to('.purple', { x: 600, duration: 1 })
tl.to('.orange', { x: 600, duration: 1 })
// 만약 동시에 실행되도록 하고싶다면
// 타임라인에서 정확히 1초 지점에서 시작 (절대적)
tl.to('.green', { x: 600, duration: 2 }, 1)
// 이전 애니메이션의 시작 부분에 삽입
tl.to('.purple', { x: 600, duration: 1 }, '<')
// 타임라인 끝에서 1초 후에 삽입 (간격)
tl.to('.orange', { x: 600, duration: 1 }, '+=1')
// 절대 시간
// 타임라인 시작부터 측정됩니다. (초 단위)
// 타임라인 시작부터 정확히 3초 지점에 삽입
tl.to('.class', {x: 100}, 3)
// 간격(gap)
// 타임라인 끝에서 1초 후 (보통 이전에 삽입된 애니메이션)
tl.to('.class', {x: 100}, '+=1')
// 삽입하는 애니메이션 총 지속 시간의 50%만큼 타임라인 끝을 넘어서
tl.to('.class', {x: 100}, '+=50%')
// 겹침(overlap)
// 타임라인 끝에서 1초 전 (보통 이전에 삽입된 애니메이션)
tl.to('.class', {x: 100}, '-=1')
// 삽입하는 애니메이션 총 지속 시간의 25%만큼 타임라인 끝과 겹치게
tl.to('.class', {x: 100}, '-=25%')
GSAP의 컨트롤
버튼 클릭이나 호버같은 특정 상호작용에서 애니메이션을 재생할 수 있도록 해준다.
// 트윈이나 타임라인을 변수에 저장
const tween = gsap.to('#logo', { duration: 1, x: 100 })
// 일시 정지
tween.pause()
// 재개 (방향 유지 - 역방향이든 아니든)
tween.resume()
// 역방향 (항상 시작 지점으로 돌아감)
tween.reverse()
// 트윈의 정확히 0.5초 지점으로 이동
tween.seek(0.5)
// 트윈 진행 상태의 정확히 1/4 지점으로 이동
tween.progress(0.25)
// 트윈을 절반 속도로 만들기
tween.timeScale(0.5)
// 트윈을 두 배 속도로 만들기
tween.timeScale(2)
// 즉시 트윈을 종료하고 가비지 컬렉션 대상으로 만들기
tween.kill()
// 제어 메서드를 연결할 수도 있다.
// 타임라인을 두 배 속도로 역방향 재생
tween.timeScale(2).reverse()
GSAP의 콜백
애니메이션이 시작될 때 알아야 하거나 애니메이션이 끝날 때 일부 JS를 실행해야 할 때 사용한다.
// 애니메이션이 완료되었을 때 호출됩니다.
onComplete
// 애니메이션이 시작될 때 호출됩니다.
onStart
// 애니메이션이 업데이트될 때마다 호출됩니다. (애니메이션이 활성화되어 있는 동안 매 프레임마다)
onUpdate
// 애니메이션이 반복될 때마다 호출됩니다.
onRepeat
// 역방향으로 재생될 때 애니메이션이 다시 시작 지점에 도달하면 호출됩니다.
onReverseComplete
오늘 배운 것들로 만들어본 애니메이션
HTML
<div class="banner">
<div class="banner__main">
<h2 class="banner__title" aria-label="창의적인 작업 과정">
<span>Creative</span>
<span>Process</span>
</h2>
<p class="banner__description">당신이 사랑하는 것들에서 영감을 찾는 방법을 배우세요.</p>
<a href="#banner-link" class="banner__link">레퍼런스</a>
</div>
<div class="banner__images">
<svg width="238" height="222" viewBox="0 0 238 222" aria-hidden="true">
<g id="items">
<g id="earth">
...
</g>
<g id="controller">
...
</g>
<g id="basketball">
...
</g>
<g id="book_1_">
...
</g>
<g id="pencil">
...
</g>
<g id="ball">
...
</g>
<g id="paint">
...
</g>
</g>
</svg>
</div>
</div>
JS
const tl = gsap.timeline({
id: "banner animation",
defaults: { opacity: 0, ease: "back.out(1.4)" },
});
tl.from(".banner", { ease: "linear", autoAlpha: 0 })
.from(".banner__title :first-child", { x: 80, duration: 1 })
.from(".banner__title :last-child", { x: -80, duration: 1 }, "<")
.from(".banner__description", { y: 30 }, "-=0.5")
.from(".banner__link", { y: 40 }, "-=0.4")
.from(
"#items > g",
{ scale: 0, transformOrigin: "center", stagger: 0.1 },
"-=0.2"
);
// GSAP 다버깅 플러그인
gsap.registerPlugin(GSDevTools);
GSDevTools.create({ animation: tl, loop: true, id: "main" });
// 이벤트 핸들링
document.querySelector(".banner").addEventListener("click", () => {
alert("devtools kill!!!!");
// 개발 도구 GSDevTools 인스턴스 제거
GSDevTools.getById("main").kill();
});
The Problem I Faced
몇몇 기능을 쓰지 않아서 아직 얼마나 어려운지 모르겠지만 확실히 이쁘고 다양한 애니메이션을 만들거라면 어려울것같다.
What I Tried to Do
How I Solved It
So
Aha Moments
전에 혼자서 토이프로젝트를 했을때에는 GSAP이 유료였는데 최근에 무료화가 되어서 편하게 사용할 수 있게 되었다.
GSAP을 사용하여 이것저것 해볼 생각에 행복하다.