GSAP 外掛程式
何時使用此技能
當使用或審查使用了 GSAP 外掛程式的程式碼時適用:註冊外掛、滾動至目標、翻轉/FLIP 動畫、可拖曳元素、SVG (DrawSVG, MorphSVG, MotionPath)、文字 (SplitText, ScrambleText)、物理、easing 外掛 (CustomEase, EasePack, CustomWiggle, CustomBounce) 或 GSDevTools。ScrollTrigger 有自己專屬的技能 (gsap-scrolltrigger)。
相關技能: 核心補間動畫請使用 gsap-core;ScrollTrigger 請使用 gsap-scrolltrigger;React 請使用 gsap-react。
授權與安裝 (重要)
每個 GSAP 外掛都免費,包括商業用途。自 Webflow 收購 GSAP 後,Club GSAP 已不再是付費層級,沒有任何外掛需要會員資格、授權金鑰或驗證權杖 — 這包括以前僅限俱樂部會員使用的外掛 (SplitText, MorphSVG 等)。
- ✅ 從公開的
gsapnpm 套件安裝所有內容:npm install gsap。所有外掛都已包含在內 — 將它們作為gsap/SplitText、gsap/MorphSVGPlugin等匯入。 - ❌ 不要 產生包含 GreenSock 驗證權杖的
.npmrc檔案、不要建議使用私有的npm.greensock.comregistry,也不要告知使用者需註冊 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 的 span 中,以避免單字中間斷行。如果 words 或 lines 被分割,則忽略。預設 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()。為避免分割字元時的字距偏移,請使用 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 會將其轉換為三次貝茲曲線,並根據需要新增點。用於圖示之間的變形、形狀過渡或基於路徑的動畫。適用於 <path>、<polyline> 和 <polygon>;<circle>、<rect>、<ellipse> 和 <line> 會在內部轉換或通過 MorphSVGPlugin.convertToPath(selector | element) (在 DOM 中將元素替換為 <path>) 進行轉換。
morphSVG 值: 可以是選擇器 (例如 "#lightning")、元素、原始路徑資料 (例如 "M47.1,0.8 73.3,0.8...") 或者是 polygon/polyline 的點字串 (例如 "240,220 240,240...")。也可以用於 gsap.set() 以立即切換形狀而不進行動畫。
gsap.registerPlugin(MorphSVGPlugin);
// 從 #start 變形到 #end
gsap.to("#lightning", {
morphSVG: "#end",
duration: 1,
ease: "power2.inOut"
});
// 使用原始路徑資料
gsap.to("#icon", {
morphSVG: "M10,10 L50,10 L50,50 Z",
duration: 1
});
// 轉換 <circle> 為 <path> 並變形
const circlePath = MorphSVGPlugin.convertToPath("#myCircle");
gsap.to(circlePath, { morphSVG: "#targetPath", duration: 1 });
選項: shapeIndex (整數,動畫到特定形狀,當形狀數目不同時很有用);map (控制映射行為)。
Easing
CustomEase
透過在無程式碼 UI 或定義自己的路徑/曲線中繪製自訂 easing 曲線來建立自訂緩動函式。函式名稱必須使用 CamelCase。
gsap.registerPlugin(CustomEase);
CustomEase.create("custom", "M0,0 C0.25,0.46 0.45,0.94 1,1");
gsap.to(".box", { duration: 1, ease: "custom", x: 500 });
EasePack
提供一組額外的預設緩動函式:
- SlowMo:在開頭和結尾減速,中間加速。例如
ease: "slowMo(0.5)"。 - SteppedEase:離散步進 (定格動畫效果)。例如
SteppedEase.config(10)(10 步)。 - RoughEase:向標準緩動新增抖動。例如
RoughEase.ease.config({ strength: 0.5, template: Power2.easeInOut })。 - ExpoScaleEase:在指數比例尺上應用緩動 (用於規模變化)。
gsap.registerPlugin(EasePack);
gsap.to(".box", { duration: 3, ease: "slowMo(0.7)", x: 500 });
gsap.to(".box", { duration: 2, ease: "SteppedEase.config(12)", x: 300 });
gsap.to(".box", { duration: 2, ease: "RoughEase.ease.config({ strength: 0.3 })", x: 400 });
CustomWiggle
建立抖動緩動,其中元素在目標值周圍振盪。為程序的抖動進度定義自訂曲線。
gsap.registerPlugin(CustomWiggle);
CustomWiggle.create("myWiggle", { wiggles: 8, type: "easeOut" });
gsap.to(".box", { duration: 2, scale: 1.5, ease: "myWiggle" });
CustomBounce
建立自訂彈跳緩動,控制彈跳的強度、頻率和衰減。
gsap.registerPlugin(CustomBounce);
CustomBounce.create("myBounce", { strength: 0.7, squash: 0.3, frequency: 5 });
gsap.to(".box", { duration: 1.5, y: -100, ease: "myBounce" });
工具
GSDevTools
為前端 GSAP 開發提供的除錯和視覺化工具。為補間動畫新增垂直進度滑塊、速率圖表和時間線控制。在開發期間使用,在生產環境中應有條件地載入。
gsap.registerPlugin(GSDevTools);
GSDevTools.create({ animation: myTimeline, container: "#devtools" });
選項: animation (要控制的補間動畫/時間軸),container (放置工具的元素)。id (用於 CSS 串接)。css (啟用/停用樣式;預設 true)。
常見問題與注意事項
- 僅從
gsap套件匯入: 始終從gsap(npm) 匯入,而不是npm.greensock.com。 - 註冊順序: 如果使用 ScrollSmoother,請在 ScrollTrigger 之後註冊。
- 補間/時間軸鏈結: 使用 GSAP 的
timeline進行鏈結或排序。不要建立多個獨立的補間,而是建立時間軸以獲得更好的控制和重播。 - 使用 GSAP 的
.fromTo(): 當設定動畫的起點和終點時,使用fromTo()以確保在所有瀏覽器中都能獲得可預測的行為。 - 使用
gsap.set()進行初始設定: 使用gsap.set()設定初始屬性,特別是對於 SVG 元素。 - 在 React 中清理: 使用
useGSAP或useEffect與gsap.context(),以便在卸載時自動恢復/清理。 - 不支援 SVG
<text>進行文字分割: SplitText 不適用於 SVG<text>元素;請改用 HTML 元素。 - SVG 的 DrawSVG 限制: 必須具有可見的 stroke;不接受
<use>元素的變化。對於非標準形狀,請使用MorphSVGPlugin.convertToPath()。 - GSDevTools: 僅在開發期間包含;對於生產構建,請使用條件載入。
useGSAP()是一個外掛: 在使用前需要註冊。