GSAP 效能 是做什麼的?
何時使用此技能
適用於最佳化 GSAP 動畫以達到流暢 60fps、降低佈局/繪製成本,或用戶詢問效能、卡頓或快速動畫最佳實務時。
相關技能: 使用 gsap-core(transforms、autoAlpha)和 gsap-timeline 建立動畫;ScrollTrigger 效能請參閱 gsap-scrolltrigger。
優先使用 Transform 和 Opacity
動畫 transform(x、y、scaleX、scaleY、rotation、rotationX、rotationY、skewX、skewY)和 opacity 可將工作保留在合成器層,避免佈局與大部分繪製。當 transform 能達到相同效果時,應避免動畫化那些會影響佈局的屬性。
- ✅ 優先使用:x、y、scale、rotation、opacity。
- ❌ 盡量避免:width、height、top、left、margin、padding(它們會觸發佈局並可能導致卡頓)。
GSAP 的 x 和 y 預設使用 transform(translate);移動時請使用它們代替 left/top。
will-change
在 CSS 中為即將動畫化的元素設定 will-change。它會提示瀏覽器提升該圖層。
will-change: transform;
批次讀取與寫入
GSAP 內部會批次更新。當混合 GSAP 與直接 DOM 讀取/寫入或依賴佈局的程式碼時,應避免交錯進行讀取與寫入,以免反覆觸發佈局抖動。建議先完成所有讀取,再進行所有寫入(或讓 GSAP 一次性處理寫入)。
大量元素(Stagger、列表)
- 若動畫相同,使用 stagger 代替多個帶有手動延遲的獨立 tween;這樣更有效率。
- 對於長列表,考慮使用虛擬化或僅動畫化可見項目;避免建立數百個同時執行的 tween 從而導致卡頓。
- 盡可能重複使用時間軸;避免每幀都建立新的時間軸。
頻繁更新的屬性(例如滑鼠跟隨器)
對於經常更新的屬性(如滑鼠跟隨器的 x/y),優先使用 gsap.quickTo()。它會重複使用單一 tween,而不是在每次更新時建立新 tween。
let xTo = gsap.quickTo("#id", "x", { duration: 0.4, ease: "power3" }),
yTo = gsap.quickTo("#id", "y", { duration: 0.4, ease: "power3" });
document.querySelector("#container").addEventListener("mousemove", (e) => {
xTo(e.pageX);
yTo(e.pageY);
});
ScrollTrigger 與效能
- pin: true 會提升被固定元素;僅根據需要固定必要元素。
- scrub 使用較小的值(例如
scrub: 1)可減少滾動過程中的工作量;請在低階裝置上測試。 - 僅在佈局實際改變時(例如內容載入後)才呼叫 ScrollTrigger.refresh(),不要每次調整大小都呼叫;盡可能進行防抖。
減少同時進行的動畫工作
- 當動畫不在可視範圍內時(例如使用者離開頁面),暫停或銷毀離螢幕或非使用中的動畫。
- 避免同時對大量元素的大量屬性進行動畫化;必要時簡化或排序。
最佳實務
- ✅ 動畫 transform 和 opacity;僅在實際動畫化的元素上使用 CSS 的 will-change。
- ✅ 當動畫相同時,使用 stagger 代替多個帶有手動延遲的獨立 tween。
- ✅ 對於頻繁更新的屬性(例如滑鼠跟隨器),使用 gsap.quickTo()。
- ✅ 清理或銷毀離螢幕的動畫;當佈局改變時呼叫 ScrollTrigger.refresh(),並盡可能進行防抖。
不應做的事
- ❌ 不要為了移動而動畫 width/height/top/left,當 x/y/scale 能達到相同外觀效果時。
- ❌ 不要「以防萬一」地在每個元素上設定 will-change 或 force3D;僅在實際動畫化的元素上使用。
- ❌ 不要建立數百個重疊的 tween 或 ScrollTrigger 卻未在低階裝置上測試。
- ❌ 不要忽略清理;殘留的 tween 和 ScrollTrigger 會持續執行並影響效能與正確性。