跳到主要內容
← 回到學習

學習 · 前端框架

React-Spring 打造最棒的動畫啊~~

目錄 · 7 個段落
  1. 01安裝
  2. 02基本用法
  3. 03常用 Hooks
  4. 04物理參數(spring config)
  5. 05進階範例:列表交錯動畫
  6. 06進階範例:進入 / 離開動畫
  7. 07React-Spring vs Framer Motion

React-Spring — 物理彈簧動畫

TL;DR
基於物理彈簧模型 的 React 動畫庫,動畫不是「線性插值 + duration」,而是 tension(張力)/ friction(摩擦力)/ mass(質量) 三個參數模擬真實物理 → 自然有機。比 Framer Motion 學習曲線陡,但動畫質感更細膩。
我的測試 repo
Bobo100/react-scroll-animation — 各種 scroll 動畫對比測試

安裝

npm install @react-spring/web
bash
套件選擇
  • @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>;
}
tsx

關鍵差別:<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)
  },
});
tsx

預設 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 });
tsx
怎麼調 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>
  );
}
tsx

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
  );
}
tsx

useTransition 自動處理 mount/unmount 跟離開動畫的延遲。


React-Spring vs Framer Motion

比較項React-SpringFramer Motion
動畫模型物理彈簧duration-based + 部分 spring
學習曲線較陡⭐ 平緩
API 風格hook-baseddeclarative props
動畫質感自然、有機流暢、可預期
Bundle 大小~25KB~50KB
Drag / Gesture要搭配 @use-gesture內建 drag、whileHover 等
場景適合細膩互動(畫布、3D、滾動)一般 UI 動畫、頁面轉場
怎麼選
  • 想快速做頁面動畫 → Framer Motion
  • 想做物理感互動 / 整合 react-three-fiber → React-Spring
  • 兩個都會 → 同一專案不要混用,挑一個就好

目錄