網頁動畫
好的網頁動態首先是設計決策,其次才是函式庫的呼叫。請依序遵循以下工作流程;只有在步驟需要時才載入規則檔案。
工作流程
1. 在選擇任何東西之前,先閱讀專案
- 檢查
package.json。如果已經安裝了動畫庫,就使用它。 不要為了單一效果而新增第二個。 - 注意框架(React / Next.js App Router / Vue / Svelte / 純 HTML)以及元件是否在伺服器端渲染(在 Next.js 中,用戶端動畫需要
"use client")。 - 檢查 CSS 變數或主題檔案中是否已有動畫標記(持續時間、緩動函數),並重複使用它們。
2. 決定動畫的目的是什麼
每個動畫都需要一個任務。每個元素選擇一個:
| 任務 | 範例 | 典型時間預算 |
|---|---|---|
| 回饋 — 確認某個動作 | 按鈕按下、切換開關、複製到剪貼簿 | 100–200ms |
| 導航 — 顯示某物從哪裡來或去哪裡 | 模態框從其觸發器開啟、列表項目重新排序、路由變更 | 200–400ms |
| 吸引注意 — 指向一個事物 | 單一主視覺序列、新的通知 | 400–1200ms,一次 |
| 敘事 — 透過滾動講述一個故事 | 固定的產品逐步導覽、可刷動的時間軸 | 與滾動距離相關 |
如果一個元素沒有任務,就不要動畫化它。一個精心編排的時刻勝過每個區塊都淡入。閱讀 rules/motion-design.md 以了解持續時間、緩動、編排以及「高級感」檢查清單。
3. 選擇能完成工作的最輕量工具
先考慮平台,再考慮函式庫:
| 需求 | 使用的工具 | 規則檔案 |
|---|---|---|
| 懸停、聚焦、按壓、簡單循環 | CSS 轉場 / @keyframes | css-keyframes.md |
| 對話框、彈出視窗、下拉選單的進場與出場 | CSS @starting-style + transition-behavior: allow-discrete | css-keyframes.md |
| 頁面 / 路由轉場、狀態之間的共享元素變形 | View Transitions API | view-transitions.md |
| 簡單的滾動連結揭示、進度條、視差 | CSS animation-timeline: view() / scroll() | scroll-animations.md |
| 固定區塊、可刷動的多步驟時間軸、橫向滾動 | GSAP + ScrollTrigger | gsap.md |
| 分割文字 / 線條遮罩標題揭示 | GSAP SplitText | gsap.md |
| React 進出場、佈局與共享佈局動畫、手勢 | Motion for React (motion/react) | framer-motion.md |
| 無框架的命令式動畫、彈簧 | Motion (motion) | motion-one.md |
| 不使用 GSAP 的 SVG 線條繪製與變形 | Anime.js v4 (svg.createDrawable, svg.morphTo) | animejs.md |
| 不相關形狀間的複雜路徑變形 | Flubber(或 GSAP MorphSVG) | flubber.md |
| After Effects 動畫播放 | Lottie (dotLottie) | lottie.md |
| 互動式、狀態驅動的插畫動畫 | Rive | rive.md |
| 動態圖表 | D3 轉場 | d3.md |
| 大量互動式 2D 形狀(編輯器、圖表) | Konva | konva.md |
| 3D、粒子、著色器 | Three.js / React Three Fiber | three-js.md |
當選擇不明顯時,閱讀 rules/choosing-library.md。
4. 以不可妥協的事項建構它
這些適用於每一個動畫,無論使用哪個函式庫:
- 動畫化
transform和opacity。 避免動畫化width、height、top、left、margin;對於佈局變更,請使用scale/translate、FLIP(GSAP Flip、Motionlayout)或 View Transitions。請參閱 rules/performance.md。 - 尊重
prefers-reduced-motion。 將移動替換為透明度淡出或立即變更;切勿只刪除內容的進場動畫,使其保持不可見。可滾動時間軸效果應變為靜態。 - 切勿在 JavaScript 執行前隱藏內容。 在 JavaScript 中(或透過
.js類別)設定初始隱藏狀態,以便在腳本失敗時內容仍可見。使用 SSR 時,透過在首次繪製前套用初始樣式,避免內容先顯示再隱藏的閃爍。 - 清理。 在卸載時還原或終止動畫(
useGSAP、createScope().revert()、gsap.context),並在路由變更時終止 ScrollTrigger。 - 保持互動即時響應。 使用者觸發的任何東西都應使用可中斷的動畫:第二次點擊不得排隊等待第一次完成。切勿為了等待動畫完成而阻止輸入。
- 不要將焦點動畫移走。 移動的元素必須保持可見的
:focus-visible狀態,而動畫化的對話框仍必須正確移動焦點。
5. 在真實瀏覽器中驗證
不要僅透過閱讀程式碼就回報動畫已完成。運行它並檢查:
- 它會播放,且結束狀態符合設計(在動畫進行中和靜止時截圖)。
- 沒有主控台錯誤,開始時沒有佈局位移。
- 模擬
prefers-reduced-motion: reduce並確認縮減版本正常運作且內容可見。 - 調整至行動裝置寬度:固定區塊和分割文字仍然正常運作(在調整大小時重新分割)。
- 滾動驅動效果在向上和向下滾動時都正常,且在頁面中間重新載入後也正常。
- 效能面板:動畫期間沒有長幀,沒有來自動畫化屬性的佈局/繪製峰值。
最小起點
// GSAP + ScrollTrigger (npm i gsap)
import gsap from "gsap";
import { ScrollTrigger } from "gsap/ScrollTrigger";
gsap.registerPlugin(ScrollTrigger);
gsap.from(".card", {
y: 40, opacity: 0, duration: 0.8, ease: "expo.out", stagger: 0.08,
scrollTrigger: { trigger: ".cards", start: "top 80%" },
});
// Motion for React (npm i motion)
import { motion, AnimatePresence } from "motion/react";
<AnimatePresence>
{open && (
<motion.div
key="panel"
initial={{ opacity: 0, y: 8 }}
animate={{ opacity: 1, y: 0 }}
exit={{ opacity: 0, y: 8 }}
transition={{ type: "spring", duration: 0.35, bounce: 0 }}
/>
)}
</AnimatePresence>
/* 純平台滾動揭示:Chrome 115+, Safari 26+, Firefox 159+ */
@media (prefers-reduced-motion: no-preference) {
@supports (animation-timeline: view()) {
.reveal {
animation: reveal linear both;
animation-timeline: view();
animation-range: entry 10% cover 30%;
}
}
}
@keyframes reveal { from { opacity: 0; translate: 0 2rem; } }
規則檔案
- rules/motion-design.md — 持續時間、緩動、編排、如何讓動態感覺高級
- rules/choosing-library.md — 決策流程、能力矩陣、衡量後的套件大小
- rules/performance.md — 僅合成器屬性、效能分析、
will-change、減少動畫 - rules/scroll-animations.md — CSS 滾動時間軸、ScrollTrigger 模式、平滑滾動
- rules/view-transitions.md — 同文件與跨文件頁面轉場
- rules/css-keyframes.md — 轉場、
@keyframes、@starting-style、linear()緩動 - rules/gsap.md — 時間軸、ScrollTrigger、SplitText、Flip、
useGSAP - rules/framer-motion.md — Motion for React:變體、
AnimatePresence、佈局、手勢 - rules/motion-one.md — Motion 原生 JavaScript:
animate、序列、scroll、inView - rules/animejs.md — Anime.js v4:時間軸、交錯、SVG 繪製與變形
- rules/lottie.md — dotLottie 播放器、控制項、事件
- rules/rive.md — 狀態機與輸入
- rules/d3.md — 資料綁定轉場
- rules/flubber.md — 路徑變形
- rules/konva.md — Canvas 2D 形狀與補間動畫
- rules/three-js.md — 場景、R3F、效能
這些技術的工作範例位於 demos/。