GSAP 플러그인
이 스킬을 사용해야 하는 경우
GSAP 플러그인을 사용하거나 검토하는 코드(플러그인 등록, 스크롤 투, 플립/FLIP 애니메이션, 드래그 가능 요소, SVG(DrawSVG, MorphSVG, MotionPath), 텍스트(SplitText, ScrambleText), 물리, 이징 플러그인(CustomEase, EasePack, CustomWiggle, CustomBounce) 또는 GSDevTools)를 작업할 때 적용하세요. ScrollTrigger는 별도의 스킬(gsap-scrolltrigger)이 있습니다.
관련 스킬: 핵심 트윈에는 gsap-core; ScrollTrigger에는 gsap-scrolltrigger; React에는 gsap-react를 사용하세요.
라이선스 및 설치 (중요)
모든 GSAP 플러그인은 무료이며, 상업적 사용도 가능합니다. Webflow의 GSAP 인수 이후 Club GSAP는 더 이상 유료 등급이 아니며, 어떤 플러그인도 멤버십, 라이선스 키 또는 인증 토큰이 필요하지 않습니다 — 여기에는 이전에 Club 전용이었던 플러그인(SplitText, MorphSVG 등)도 포함됩니다.
- ✅ 모든 것은 공개
gsapnpm 패키지에서 설치하세요:npm install gsap. 모든 플러그인이 포함되어 있습니다.gsap/SplitText,gsap/MorphSVGPlugin등으로 가져오세요. - ❌ GreenSock 인증 토큰이 있는
.npmrc를 생성하거나, 비공개npm.greensock.com레지스트리를 제안하거나, 사용자에게 플러그인에 접근하기 위해 Club GSAP에 가입하라고 알리지 마세요. 해당 지침은 구식입니다.
플러그인 등록
각 플러그인을 한 번 등록하여 GSAP(및 번들러)가 이를 포함하도록 해야 합니다. 프로젝트에서 사용하는 모든 플러그인과 함께 gsap.registerPlugin() 을 사용하세요:
import gsap from "gsap";
import { ScrollToPlugin } from "gsap/ScrollToPlugin";
import { Flip } from "gsap/Flip";
import { Draggable } from "gsap/Draggable";
gsap.registerPlugin(ScrollToPlugin, Flip, Draggable);
- ✅ 트윈 또는 API 호출에서 플러그인을 사용하기 전에 등록하세요.
- ✅ React에서는 최상위 수준 또는 앱에서 한 번 등록하세요(예: 첫 번째 useGSAP 전에); 다시 렌더링되는 컴포넌트 내부에서 등록하지 마세요. useGSAP는 사용 전에 등록해야 하는 플러그인입니다.
스크롤
ScrollToPlugin
스크롤 위치(창 또는 스크롤 가능한 요소)를 애니메이션화합니다. ScrollTrigger 없이 "요소로 스크롤" 또는 "위치로 스크롤"할 때 사용하세요.
gsap.registerPlugin(ScrollToPlugin);
gsap.to(window, { duration: 1, scrollTo: { y: 500 } });
gsap.to(window, { duration: 1, scrollTo: { y: "#section", offsetY: 50 } });
gsap.to(scrollContainer, { duration: 1, scrollTo: { x: "max" } });
ScrollToPlugin — 주요 설정 (scrollTo 객체):
| 옵션 | 설명 |
|---|---|
x, y | 대상 스크롤 위치(숫자) 또는 최대값의 경우 "max" |
element | 스크롤할 요소의 선택자 또는 요소 (스크롤-인투-뷰) |
offsetX, offsetY | 대상 위치로부터의 오프셋 (픽셀 단위) |
ScrollSmoother
부드러운 스크롤 래퍼 (네이티브 스크롤을 부드럽게). ScrollTrigger와 특정 DOM 구조(콘텐츠 래퍼 + 부드러운 래퍼)가 필요합니다. 부드럽고 관성 스타일의 스크롤이 필요할 때 사용하세요. 설정은 GSAP 문서를 참조하세요; ScrollTrigger 후에 등록하세요. DOM 구조는 다음과 같습니다:
<body>
<div id="smooth-wrapper">
<div id="smooth-content">
<!--- 모든 콘텐츠는 여기에 --->
</div>
</div>
<!-- position: fixed 요소는 외부에 배치 가능 --->
</body>
DOM / UI
Flip
Flip.getState()로 상태를 캡처한 다음, 변경 사항(예: 레이아웃 또는 클래스 변경)을 적용하고, Flip.from()을 사용하여 이전 상태에서 새 상태로 애니메이션화합니다(FLIP: First, Last, Invert, Play). 두 레이아웃 상태(목록, 그리드, 확장/축소) 사이를 애니메이션화할 때 사용하세요.
gsap.registerPlugin(Flip);
const state = Flip.getState(".item");
// DOM 변경 (재정렬, 추가/제거, 클래스 변경)
Flip.from(state, { duration: 0.5, ease: "power2.inOut" });
Flip — 주요 설정 (Flip.from vars):
| 옵션 | 설명 |
|---|---|
absolute | 플립 중 position: absolute 사용 (기본값: false) |
nested | true인 경우 첫 번째 수준의 자식만 측정됨 (중첩 변환에 더 좋음) |
scale | true인 경우 요소를 맞게 크기 조정 (늘어짐 방지); 기본값 true |
simple | true인 경우 위치/크기만 애니메이션화됨 (더 빠르고 덜 정확함) |
duration, ease | 표준 트윈 옵션 |
추가 정보
https://gsap.com/docs/v3/Plugins/Flip
Draggable
마우스/터치로 요소를 드래그, 회전 또는 던질 수 있게 만듭니다. 슬라이더, 카드, 재정렬 가능한 목록 또는 모든 드래그 상호작용에 사용하세요.
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".box", { type: "x,y", bounds: "#container", inertia: true });
Draggable.create(".knob", { type: "rotation" });
Draggable — 주요 설정 옵션:
| 옵션 | 설명 |
|---|---|
type | "x", "y", "x,y", "rotation", "scroll" |
bounds | 요소, 선택자 또는 { minX, maxX, minY, maxY }로 드래그 제한 |
inertia | true로 던지기/관성 활성화 (InertiaPlugin 필요) |
edgeResistance | 0–1; 경계를 넘어 드래그할 때 저항 |
cursor | 드래그 중 CSS 커서 |
onDragStart, onDrag, onDragEnd | 콜백; 이벤트와 대상 수신 |
onThrowUpdate, onThrowComplete | 관성 활성화 시 콜백 |
Inertia (InertiaPlugin)
Draggable과 함께 사용하여 릴리스 후 관성을 제공하거나, 모든 객체의 모든 속성의 관성/속도를 추적하여 간단한 트윈으로 매끄럽게 정지하도록 합니다. inertia: true 사용 시 Draggable과 함께 등록하세요:
gsap.registerPlugin(Draggable, InertiaPlugin);
Draggable.create(".box", { type: "x,y", inertia: true });
또는 속성의 속도를 추적합니다:
InertiaPlugin.track(".box", "x");
그런 다음 "auto"를 사용하여 현재 속도를 유지하고 정지합니다:
gsap.to(obj, { inertia: { x: "auto" } });
Observer
장치 간 포인터 및 스크롤 입력을 정규화합니다. ScrollTrigger처럼 스크롤 위치에 직접 연결하지 않고 스와이프, 스크롤 방향 또는 사용자 정의 제스처 로직에 사용하세요.
gsap.registerPlugin(Observer);
Observer.create({
target: "#area",
onUp: () => {},
onDown: () => {},
onLeft: () => {},
onRight: () => {},
tolerance: 10
});
Observer — 주요 설정 옵션:
| 옵션 | 설명 |
|---|---|
target | 관찰할 요소 또는 선택자 |
onUp, onDown, onLeft, onRight | 스와이프/스크롤이 해당 방향의 허용 오차를 초과할 때 콜백 |
tolerance | 방향이 감지되기 전 픽셀; 기본값 10 |
type | "touch", "pointer" 또는 "wheel" (기본값: "touch,pointer") |
텍스트
SplitText
요소의 텍스트를 문자, 단어 및/또는 줄(각각 자체 요소에)로 분할하여 지연 또는 단위별 애니메이션을 가능하게 합니다. 텍스트를 문자별, 단어별 또는 줄별로 애니메이션화할 때 사용하세요. chars, words, lines(및 mask가 설정된 경우 masks)가 있는 인스턴스를 반환합니다. revert() 또는 gsap.context() 로 원본 마크업을 복원하세요. gsap.context(), matchMedia() 및 useGSAP() 와 통합됩니다. API: SplitText.create(target, vars) (target = 선택자, 요소 또는 배열).
gsap.registerPlugin(SplitText);
const split = SplitText.create(".heading", { type: "words, chars" });
gsap.from(split.chars, { opacity: 0, y: 20, stagger: 0.03, duration: 0.4 });
// 나중에: split.revert() 또는 gsap.context() 정리로 되돌리기
onSplit() (v3.13.0+)을 사용하면 autoSplit이 사용될 때 각 분할 및 재분할 시 애니메이션이 실행됩니다. onSplit() 에서 트윈/타임라인을 반환하면 SplitText가 재분할 시 정리하고 진행 상황을 동기화할 수 있습니다:
SplitText.create(".split", {
type: "lines",
autoSplit: true,
onSplit(self) {
return gsap.from(self.lines, { y: 100, opacity: 0, stagger: 0.05, duration: 0.5 });
}
});
SplitText — 주요 설정 (SplitText.create vars):
| 옵션 | 설명 |
|---|---|
| type | 쉼표로 구분: "chars", "words", "lines". 기본값 "chars,words,lines". 성능을 위해 필요한 부분만 분할하세요(예: 줄을 사용하지 않으면 "words, chars"). chars만 단독으로 사용하지 말고 words/lines와 함께 사용하거나 smartWrap: true를 사용하여 비정상적인 줄 바꿈을 방지하세요. |
| charsClass, wordsClass, linesClass | 각 분할 요소의 CSS 클래스. 증가하는 클래스를 추가하려면 "++"를 추가하세요(예: linesClass: "line++" → line1, line2, …). |
| aria | "auto" (기본값), "hidden" 또는 "none". 접근성: "auto"는 분할 요소에 aria-label을 추가하고 줄/단어/문자 요소에 aria-hidden을 추가하여 화면 리더가 레이블을 읽도록 함; "hidden"은 리더에서 모든 것을 숨김; "none"은 aria를 변경하지 않음. 중첩된 링크/의미론이 노출되어야 하는 경우 중복된 화면 리더 전용 복사본과 함께 "none"을 사용하세요. |
| autoSplit | true인 경우 글꼴 로딩이 완료되거나 요소 너비가 변경될 때(그리고 줄이 분할된 경우) 되돌리고 다시 분할하여 잘못된 줄 바꿈을 방지합니다. 애니메이션은 onSplit() 내부에서 생성되어야 새로 분할된 요소를 대상으로 함; 재분할 시 자동 정리 및 시간 동기화를 위해 onSplit() 에서 애니메이션을 반환하세요. |
| onSplit(self) | 분할이 완료될 때 콜백(그리고 autoSplit이 true인 경우 각 재분할 시). SplitText 인스턴스를 수신합니다. GSAP 트윈 또는 타임라인을 반환하면 재분할 시 해당 애니메이션의 자동 되돌리기/동기화가 활성화됩니다. |
| mask | "lines", "words" 또는 "chars". 마스크/공개 효과를 위해 각 단위를 overflow: clip이 있는 추가 요소로 감쌉니다. 하나의 유형만; 인스턴스의 masks 배열에서 래퍼에 접근하세요(또는 클래스가 설정된 경우 -mask 클래스 사용). |
| tag | 래퍼 요소 태그; 기본값 "div". 인라인의 경우 "span" 사용 (참고: 회전/크기 조정과 같은 변환은 일부 브라우저에서 인라인 요소에 렌더링되지 않을 수 있음). |
| deepSlice | true(기본값)인 경우 여러 줄에 걸쳐 있는 중첩 요소(예: <strong>)는 줄이 수직으로 늘어나지 않도록 세분화됩니다. 줄을 분할할 때만 적용됩니다. |
| ignore | 분할되지 않은 상태로 둘 선택자 또는 요소 (예: ignore: "sup"). |
| smartWrap | chars만 분할할 때, 단어를 white-space: nowrap 범위로 감싸서 단어 중간 줄 바꿈을 방지합니다. 단어 또는 줄이 분할된 경우 무시됩니다. 기본값 false. |
| wordDelimiter | 단어 경계: 문자열(기본값 " "), RegExp 또는 사용자 정의 분할을 위한 { delimiter: RegExp, replaceWith: string } (예: 해시태그 또는 비라틴어용 제로 너비 조이너). |
| prepareText(text, parent) | 원시 텍스트와 부모 요소를 수신하는 함수; 분할 전에 수정된 텍스트를 반환함 (예: 공백이 없는 언어에 중단 표시를 삽입). |
| propIndex | true인 경우 각 분할 요소에 인덱스가 있는 CSS 변수 추가 (예: --word: 1, --char: 2). |
| reduceWhiteSpace | 연속된 공백을 축소; 기본값 true. v3.13.0부터 줄 바꿈을 존중하고 <pre>에 <br>을 삽입할 수 있음. |
| onRevert | 인스턴스가 되돌려질 때 콜백. |
팁: 애니메이션할 부분만 분할하세요(예: 단어만 애니메이션한다면 chars 건너뛰기). 사용자 정의 글꼴의 경우 로드 후 분할하거나(예: document.fonts.ready.then(...)) autoSplit: true와 onSplit() 을 사용하세요. chars 분할 시 커닝 이동을 방지하려면 CSS font-kerning: none; text-rendering: optimizeSpeed;를 사용하세요. text-wrap: balance는 분할을 방해할 수 있으므로 피하세요. SplitText는 SVG <text>를 지원하지 않습니다.
자세히 알아보기: SplitText
ScrambleText
스크램블/글리치 효과로 텍스트를 애니메이션화합니다. 스크램블로 텍스트를 공개하거나 전환할 때 사용하세요.
gsap.registerPlugin(ScrambleTextPlugin);
gsap.to(".text", {
duration: 1,
scrambleText: { text: "New message", chars: "01", revealDelay: 0.5 }
});
SVG
DrawSVG (DrawSVGPlugin)
stroke-dashoffset / stroke-dasharray를 애니메이션화하여 SVG 요소의 선을 공개하거나 숨깁니다. <path>, <line>, <polyline>, <polygon>, <rect>, <ellipse>에서 작동합니다. 선을 "그리기" 또는 "지우기"할 때 사용하세요.
drawSVG 값: 경로를 따라 선의 보이는 세그먼트 (시작 및 끝 위치)를 설명하며, "시간이 지남에 따라 A에서 B로 애니메이션"하는 것이 아닙니다. 형식: 퍼센트 또는 길이 단위의 "start end". 예: "0% 100%" = 전체 선; "20% 80%" = 20%와 80% 사이에서만 선 (양쪽 끝에 간격). 트윈은 요소의 현재 세그먼트에서 대상 세그먼트로 애니메이션됩니다 — 예: gsap.to("#path", { drawSVG: "0% 100%" })는 현재 상태에서 전체 선으로 이동. 단일 값(예: 0, "100%")은 시작이 0임을 의미: "100%"는 "0% 100%"와 동일.
필수: 요소에 보이는 선이 있어야 함 — CSS 또는 SVG 속성으로 stroke 및 stroke-width 설정; 그렇지 않으면 아무것도 그려지지 않습니다.
gsap.registerPlugin(DrawSVGPlugin);
// 아무것도 없는 상태에서 전체 선으로 그리기
gsap.from("#path", { duration: 1, drawSVG: 0 });
// 또는 명시적 세그먼트: 0–0에서 0–100%로
gsap.fromTo("#path", { drawSVG: "0% 0%" }, { drawSVG: "0% 100%", duration: 1 });
// 중간에만 선 (끝에 간격)
gsap.to("#path", { duration: 1, drawSVG: "20% 80%" });
주의 사항: 선에만 영향을 미칩니다(채우기 아님). 단일 세그먼트 <path> 요소를 선호하세요; 다중 세그먼트 경로는 일부 브라우저에서 이상하게 렌더링될 수 있습니다. <use>의 내용은 시각적으로 변경할 수 없습니다. DrawSVGPlugin.getLength(element) 및 DrawSVGPlugin.getPosition(element) 는 선 길이와 현재 위치를 반환합니다.
자세히 알아보기: DrawSVG
MorphSVG (MorphSVGPlugin)
d 속성(경로 데이터)을 애니메이션화하여 하나의 SVG 모양을 다른 모양으로 변형합니다. 시작 및 끝 모양은 동일한 수의 점이 필요하지 않습니다 — MorphSVG는 3차 베지어로 변환하고 필요에 따라 점을 추가합니다. 아이콘 간 변형, 모양 전환 또는 경로 기반 애니메이션에 사용하세요. <path>, <polyline> 및 <polygon>에서 작동; <circle>, <rect>, <ellipse> 및 <line>은 내부적으로 변환되거나 MorphSVGPlugin.convertToPath(선택자 | 요소) (DOM에서 요소를 <path>로 대체)를 통해 변환됩니다.
morphSVG 값: 선택자 (예: "#lightning"), 요소, 원시 경로 데이터 (예: "M47.1,0.8 73.3,0.8…") 또는 폴리곤/폴리라인의 경우 점 문자열 (예: "240,220 240,210…")일 수 있습니다. "#lightning"과 같은 선택자의 경우 시작 모양과 대상 모양이 동일한 유형이어야 함을 의미하는 "end: #target" 또는 "from: #start, to: #end" 형식을 사용할 수도 있습니다. 대상이 { shape: "#target" } 객체인 경우 단일 선택자도 암시적 "to" 대상으로 간주됩니다.
gsap.registerPlugin(MorphSVGPlugin);
// 간단한 변형: