Velocity Skew
依滾動速度即時傾斜與模糊內容,停止滾動時以彈簧平滑回正,帶來富有動能的閱讀質感。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
8
4
1200
350
60
<VelocitySkew />
安裝
npx shadcn@latest add https://webberui.com/r/velocity-skew.json或在 components.json 設定 registries 後,改用 @webberui/velocity-skew 安裝。
安裝依賴後,從 registry JSON(/r/velocity-skew.json 的 files[0].content)複製 velocity-skew.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge使用
import { VelocitySkew } from "@/components/ui/velocity-skew";
<VelocitySkew className="flex flex-col gap-3">
<Card>第一列</Card>
<Card>第二列</Card>
<Card>第三列</Card>
</VelocitySkew>預設每個直接子元素會各自傾斜;若滾動發生在巢狀 overflow 容器內,把該容器的 ref 傳給 container:
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[300px] overflow-y-auto">
<VelocitySkew container={scrollerRef} maxSkew={9} maxBlur={3}>
{/* … */}
</VelocitySkew>
</div>Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 要隨滾動速度反應的內容 |
container | React.RefObject<HTMLElement | null> | — | 巢狀捲動容器的 ref;預設以視窗為捲動容器 |
maxSkew | number | 8 | 傾斜的最大角度(度),設為 0 停用傾斜 |
maxBlur | number | 4 | 模糊的最大強度(px),設為 0 停用模糊 |
maxVelocity | number | 1200 | 達到最大效果所需的滾動速度(px/s),越小越靈敏 |
stiffness | number | 350 | 平滑用彈簧剛性,越高回正越快 |
damping | number | 60 | 平滑用彈簧阻尼,越高越不易來回擺盪 |
combine | boolean | false | true 時整塊內容一起傾斜;預設每個子元素各自傾斜 |
className | string | — | 外層容器的 class |
itemClassName | string | — | 每個子元素包裹層的 class(combine 模式下無效) |
細節
- 以
useScroll取得捲動位移,再經useVelocity換算為速度,最後透過useSpring平滑,避免抖動並在停手後自然回正。 - 傾斜方向隨滾動方向翻轉(向下為負角、向上為正角),速度越快傾斜與模糊越強,並在
maxVelocity處達到上限。 maxBlur為0時不會套用filter,可省去建立合成層的開銷。
可及性
- 使用者系統開啟「減少動態效果」時,保留原始版面並移除所有速度驅動的傾斜與模糊。
- 元件不攔截焦點或鍵盤行為,內容維持原本的語意與可讀性;範例中的捲動容器帶
tabIndex與aria-label,可用鍵盤滾動。