F05▸A012▸framer-motion
Number Count Up
數字滾動
難度 ★★★★★標籤 數字 · animate · useInView2 min read
效果簡述
數字從 0 跳到目標值,常用在 KPI / 訂閱數 / 轉換率展示。用 framer-motion
的 animate() 函式驅動 + useInView 觸發即可,不用裝額外套件。
0
累計數字(示意)· 1.8s
Claude Code Prompt
參考:A012 number count up
技術:framer-motion animate() + useInView
具體行為:
- ref 綁 span,useInView(ref, { once: true, amount: 0.5 })
- inView 時呼叫 animate(0, target, { duration: 1.8, ease: [0.2,0.8,0.2,1], onUpdate: v => setN(Math.round(v)) })
- 顯示用 toLocaleString() 加千分位
- cleanup: controls.stop() in unmount
限制:
- duration 1.5~2 秒
- 大數字才有戲(小於 20 沒感)
- 不要每個都加,一頁 1~3 個夠完整程式碼
'use client'
import { animate, useInView } from 'framer-motion'
import { useEffect, useRef, useState } from 'react'
export function NumberCountUp({ target = 12450 }: { target?: number }) {
const ref = useRef<HTMLSpanElement>(null)
const inView = useInView(ref, { once: true, amount: 0.5 })
const [n, setN] = useState(0)
useEffect(() => {
if (!inView) return
const controls = animate(0, target, {
duration: 1.8,
ease: [0.2, 0.8, 0.2, 1],
onUpdate: (v) => setN(Math.round(v)),
})
return () => controls.stop()
}, [inView, target])
return <span ref={ref}>{n.toLocaleString()}</span>
}何時用
- ✅ Landing page KPI 展示
- ✅ Dashboard 數字進場
- ✅ 成就解鎖 / 統計總結
何時別用
- ❌ 數字頻繁變動的場景(每次都跳一遍很煩)
- ❌ 表格 / 列表內的多個數字(會閃成一片)
- ❌ 小數字(< 20 沒戲劇感)
我踩過的坑
-
沒 cleanup 切頁會 warning:unmount 時不 stop(),React 會抱怨 setState on unmounted。
return () => controls.stop()一定要。 -
Math.round(v)不能漏:不取整會看到 12449.7382 那種抖動。 -
大數字加
toLocaleString():12450 → 12,450 才好讀。
相關效果
- F12 whileInView Trigger — 入視口觸發概念