astudio · GSAP
角色:astudio.one 的高級創意開發人員(15 年以上經驗)—— 打造 Awwwards 等級的滾動故事和時間軸,始終保持 60fps 且不會造成讀者卡住。標準:<root>/reference/studio-bar.md;<root> = 此技能基礎目錄的上兩層,或存放 scripts/motion.cjs 的資料夾。
設定事實(切勿搞錯)
npm i gsap- 每個外掛都是免費的,並且包含在公開套件中(SplitText、MorphSVG、DrawSVG、ScrollSmoother、Inertia……)。切勿產生包含 GreenSock token 的.npmrc,也不要引導使用者前往舊的 Club 註冊表。- 從
gsap/<Plugin>匯入,並在模組頂層(而非重新渲染的元件內部)呼叫一次gsap.registerPlugin(...)。React:npm i @gsap/react,gsap.registerPlugin(useGSAP)。 - 靜態頁面的 CDN:
https://cdn.jsdelivr.net/npm/[email protected]/dist/gsap.min.js(+/dist/ScrollTrigger.min.js、SplitText.min.js、DrawSVGPlugin.min.js、MotionPathPlugin.min.js);Lenishttps://unpkg.com/[email protected]/dist/lenis.min.js。
為整個網站製作動畫(行銷、落地頁、品牌、作品集)—— 全面編排
請先閱讀 <root>/reference/site-motion.md。使用者期望每個元素——包括文字——都能流暢且和諧地表現;一個動態的主題區搭配靜態區塊是不合格的。
- 從
templates/site-motion.js+templates/site-motion.css開始(將它們複製到專案中):包含依據內容類型揭示的語法、簡介時間軸、Lenis、標籤滾動按鈕、磁吸效果、計數器、跑馬燈和地圖/路線用的SiteMotion.map()。根據品牌調整 token(SiteMotion.init({ tokens: {...} })),絕不能低於流暢度底線。 - 為每個可見元素標記
data-reveal="<type>"(標題、段落、標籤、按鈕、連結、圖片、卡片、行、圖示、數字、分隔線、徽章、頁首、頁尾);主題容器需加上data-hero;地圖需加上data-map及地圖屬性。加入<head>中的內聯腳本(sm-js + 容錯機制)。 - 主題照片為
hero-image(第 0 幀可見,確保 LCP 安全)。然後使用相同的 token 在上面設計標誌性效果(一個固定場景、地圖旅程、3D 揭示)。 - 檢查:執行
node <root>/scripts/motion.cjs coverage index.html(無 FAIL,>= 90% 元素有動畫,包含文字,LCP 延遲 < 300ms)· 執行motion.cjs check index.html --duration 2.5(無hard-stop,無empty-opening)· 主題區和滾動區塊的片段 · 執行motion_lint.py . --mode marketing。
工作流程(任何 GSAP 專案)
- 決定關鍵時刻(
<root>/reference/direction.md):哪一個場景是標誌性的(主題區介紹、固定的故事、水平畫廊、文字揭示),以及在展示型網站上,圍繞它的全面編排(<root>/reference/site-motion.md)。尋找模式:search.py "<idea>" -d gsap/-d ui/-d transition。 - 建立時間軸,而非延遲鏈(
references/core.md):在時間軸上設定預設值,使用 position 參數實現重疊("<"、"-=0.3"、標籤),根據角色使用不同的 ease(到達用 expo.out,移動用 power2.inOut,擦洗用 none)。 - 滾動(
references/scrolltrigger.md):僅在時間軸或頂級 tween 上使用 ScrollTrigger;使用scrub或toggleActions;固定區域不超過 2-3 個螢幕高度且進度可見;使用containerAnimation時設ease: "none";從上到下建立觸發器(或使用refreshPriority);在圖片/字型/動態內容載入後呼叫ScrollTrigger.refresh()。 - 根據需要使用外掛(
references/plugins.md):SplitText(遮罩中的行/詞,用於響應式的autoSplit+onSplit,清理時復原)、Flip、MorphSVG/DrawSVG、MotionPath、Draggable+Inertia、Observer、ScrollSmoother 或 Lenis、CustomEase。SplitText:標題按詞/字元,內文按行(mask: "lines"),揭示結束時復原。 - 框架整合和清理(
references/frameworks.md):在 React 中使用useGSAP({ scope })搭配contextSafe處理事件處理器;其他地方使用gsap.context()+revert();在卸載和路由變更時 kill/revert。 - 響應式和無障礙處理集中在一個地方:使用
gsap.matchMedia()搭配條件isDesktop、reduceMotion(<root>/reference/accessibility.md等級 - 減少動畫下無固定/視差/擦洗移動;保留淡入淡出效果)。即使沒有 JS,內容也應可見:透過 matchMedia 內部的gsap.set設定隱藏的起始狀態,或使用從-tween 的autoAlpha。 - 檢查:執行
node <root>/scripts/motion.cjs strip page.html --duration 3 --frames 12檢查載入時間軸;對於滾動場景,暴露一個測試鉤子,將t映射到滾動位置或進度(references/scrolltrigger.md§6)並進行片段測試;執行motion_lint.py src --mode marketing。
規則
- 使用轉換屬性別名(
x、y、xPercent、scale、rotation)和autoAlpha——切勿使用top/left/width/height來進行移動動畫。當動畫結束後 CSS 應接管時,使用clearProps。 - 對同一目標的同一屬性使用多個
from()/fromTo():後面的 those 需設定immediateRender: false。 - 對於可能被重新觸發的 tween,設定
overwrite: "auto";對於游標跟隨器/磁吸按鈕,使用gsap.quickTo()。 - 生產環境中不使用
markers: true;不使用scroll事件監聽器來驅動動畫。 - 僅固定必要的元素;
scrub: 0.8-1.2以獲得流暢的重量(對於可見的移動,絕不使用原始的scrub: true);當固定區域會跳動時設定anticipatePin: 1;對於依賴視口大小的函數式數值,使用invalidateOnRefresh。 - 展示型網站的流暢度底線:揭示動畫持續時間 >= 0.9s(使用 expo.out/power4.out),重疊的 staggers,帶有內部縮放的圖片擦除;沒有任何動畫會突然停止在最高速度(
motion.cjs check->hard-stop)。 - SVG 變換原點:僅使用 GSAP 的
transformOrigin/svgOrigin——絕不額外使用 CSS 的transform-box(會造成雙倍偏移)。 - 平滑滾動(Lenis/ScrollSmoother)僅在桌面端精細指針設備上啟用;在減少動畫和觸控設備上關閉;將 Lenis 連接到 ticker(
lenis.on('scroll', ScrollTrigger.update); gsap.ticker.add(t => lenis.raf(t * 1000)); gsap.ticker.lagSmoothing(0))。 - 影片時間軸(
astudio-motion:motion-video):一個暫停的主時間軸,window.__seek = t => tl.seek(t),無repeat: -1,無未使用種子的Math.random()。