React-Spring 打造最棒的動畫啊~~
React-Spring — 物理彈簧動畫
TL;DR基於物理彈簧模型 的 React 動畫庫,動畫不是「線性插值 + duration」,而是 tension(張力)/ friction(摩擦力)/ mass(質量) 三個參數模擬真實物理 → 自然有機。比 Framer Motion 學習曲線陡,但動畫質感更細膩。
我的測試 repoBobo100/react-scroll-animation — 各種 scroll 動畫對比測試
安裝
npm install @react-spring/web
套件選擇
@react-spring/web— DOM(HTML / SVG)@react-spring/three— react-three-fiber(3D)@react-spring/native— React Native只裝你需要的 target,別裝整個
react-spring(已 deprecated)。
基本用法
import { useSpring, animated } from '@react-spring/web';
function FadeIn() {
const styles = useSpring({
from: { opacity: 0, transform: 'translateY(20px)' },
to: { opacity: 1, transform: 'translateY(0px)' },
});
return <animated.div style={styles}>淡入效果</animated.div>;
}
關鍵差別:<animated.div> 不是普通 div,是 React-Spring 提供的「會接受 spring 物件」的 wrapper。普通 <div> 會把 SpringValue 當字串渲染。
常用 Hooks
| Hook | 用途 | 範例情境 |
|---|---|---|
useSpring | 單一元素動畫 | 淡入、卡片展開 |
useSprings | 陣列,多個元素各自動畫 | 列表項目逐個進入 |
useTrail | 多個元素 交錯延遲 動畫 | 文字逐字出現 |
useTransition | 元素 進入 / 離開 動畫 | route 轉場、tab 切換 |
useChain | 鏈接多個 spring 動畫 | 複合動畫(先 A 完才 B) |
物理參數(spring config)
const styles = useSpring({
from: { opacity: 0 },
to: { opacity: 1 },
config: {
tension: 170, // 張力越大彈越快(預設 170)
friction: 26, // 摩擦越大越快停(預設 26)
mass: 1, // 質量越大慣性越強(預設 1)
},
});
預設 config presets
import { config } from '@react-spring/web';
// config.default — 普通(170/26/1)
// config.gentle — 柔和(120/14/1)
// config.wobbly — 彈性(180/12/1)
// config.stiff — 硬挺(210/20/1)
// config.slow — 慢(280/60/1)
// config.molasses — 超慢糖漿(280/120/1)
useSpring({ ..., config: config.wobbly });
怎麼調 config用 react-spring-visualizer 視覺化調 tension/friction/mass。自己用數字試最快學會物理感覺。
進階範例:列表交錯動畫
import { useTrail, animated } from '@react-spring/web';
function StaggeredList({ items }: { items: string[] }) {
const trail = useTrail(items.length, {
from: { opacity: 0, transform: 'translateY(20px)' },
to: { opacity: 1, transform: 'translateY(0px)' },
});
return (
<ul>
{trail.map((style, i) => (
<animated.li key={items[i]} style={style}>
{items[i]}
</animated.li>
))}
</ul>
);
}
useTrail 自動讓每個元素 stagger,不用手動算 delay。
進階範例:進入 / 離開動畫
import { useTransition, animated } from '@react-spring/web';
function ModalToggle({ open, content }: Props) {
const transitions = useTransition(open, {
from: { opacity: 0, transform: 'scale(0.9)' },
enter: { opacity: 1, transform: 'scale(1)' },
leave: { opacity: 0, transform: 'scale(0.9)' },
});
return transitions((style, isOpen) =>
isOpen ? (
<animated.div style={style} className="modal">
{content}
</animated.div>
) : null
);
}
useTransition 自動處理 mount/unmount 跟離開動畫的延遲。
React-Spring vs Framer Motion
| 比較項 | React-Spring | Framer Motion |
|---|---|---|
| 動畫模型 | 物理彈簧 | duration-based + 部分 spring |
| 學習曲線 | 較陡 | ⭐ 平緩 |
| API 風格 | hook-based | declarative props |
| 動畫質感 | 自然、有機 | 流暢、可預期 |
| Bundle 大小 | ~25KB | ~50KB |
| Drag / Gesture | 要搭配 @use-gesture | 內建 drag、whileHover 等 |
| 場景適合 | 細膩互動(畫布、3D、滾動) | 一般 UI 動畫、頁面轉場 |
怎麼選
- 想快速做頁面動畫 → Framer Motion
- 想做物理感互動 / 整合 react-three-fiber → React-Spring
- 兩個都會 → 同一專案不要混用,挑一個就好