WebberUI

Rolling Number

odometer 式數字滾輪:value 變化時每一位數字獨立以 spring 垂直滾到新值,位數增減時新位淡入、舊位收攏。

載入預覽⋯

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

12345
0
<RollingNumber />

安裝

npx shadcn@latest add https://webberui.com/r/rolling-number.json

或在 components.json 設定 registries 後,改用 @webberui/rolling-number 安裝。

安裝依賴後,從 registry JSON(/r/rolling-number.jsonfiles[0].content)複製 rolling-number.tsx 原始碼到你的 components/ui/ 目錄:

npm install motion clsx tailwind-merge

使用

import { RollingNumber } from "@/components/ui/rolling-number";

const [price, setPrice] = React.useState(1280);

<RollingNumber value={price} prefix="$" className="text-5xl font-bold" />

只要更新 value,各位數字就會自動滾到新值。字級、字重、顏色都由 className 控制,元件內部以 em 為單位計算滾輪高度,任何字級下都對齊。

帶小數與後綴:

<RollingNumber value={98.6} decimals={1} suffix="%" />

Props

RollingNumber

Prop型別預設值說明
valuenumber要顯示的數值,變化時每一位數字以滾輪滾動到新值
decimalsnumber0小數位數
prefixstring""數字前綴(例如 $
suffixstring""數字後綴(例如 +%
localestring"en-US"Intl.NumberFormat locale,決定千分位與小數點符號
springConfigSpringOptions{ stiffness: 300, damping: 30, mass: 0.8 }滾輪的 spring 參數
classNamestring附加到最外層 <span> 的 class

細節

  • 與 Animated Stats 的差異:Animated Stats 是整數 count-up——單一 MotionValue 從 0 補間到目標值、整串文字逐格重寫;Rolling Number 是 odometer 式——每一位數字是一個獨立的垂直滾輪(0–9 縱向堆疊的 column),value 變化時各滾輪分別滾到自己的目標數字。前者適合進場一次性的統計數字,後者適合會反覆變動的即時數值(價格、庫存、計數器)
  • 滾輪機制:每個 digit column 高度 1emoverflow: hidden,內部 0–9 各佔 1em 縱向堆疊,spring 驅動 translateY = -digit * 1em 滾到目標格
  • stagger:由低位到高位(個位先滾)每位延遲 0.03 秒,形成機械儀表的連動感
  • 位數增減:字元 key 以「從右數」的位置編排,個位永遠是同一顆滾輪;位數增加時新位(與新的千分位逗號)從左側淡入並展開寬度,位數減少時舊位收攏寬度淡出(AnimatePresence + width 動畫)
  • 分隔字元:千分位逗號與小數點由 Intl.NumberFormat 產生,為靜態字元不參與滾動;整體套用 tabular-nums,數字等寬、滾動時不抖動

可及性

  • 使用者系統開啟「減少動態效果」時,跳過滾輪與位數過渡,直接顯示新值的靜態文字
  • 容器帶 aria-label(完整格式化值,含前後綴),滾輪層對輔助科技隱藏(aria-hidden),螢幕閱讀器只會朗讀當前完整數值,不會唸出滾輪裡的 0–9

On this page