WebberUI

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.jsonfiles[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型別預設值說明
childrenReact.ReactNode要隨滾動速度反應的內容
containerReact.RefObject<HTMLElement | null>巢狀捲動容器的 ref;預設以視窗為捲動容器
maxSkewnumber8傾斜的最大角度(度),設為 0 停用傾斜
maxBlurnumber4模糊的最大強度(px),設為 0 停用模糊
maxVelocitynumber1200達到最大效果所需的滾動速度(px/s),越小越靈敏
stiffnessnumber350平滑用彈簧剛性,越高回正越快
dampingnumber60平滑用彈簧阻尼,越高越不易來回擺盪
combinebooleanfalsetrue 時整塊內容一起傾斜;預設每個子元素各自傾斜
classNamestring外層容器的 class
itemClassNamestring每個子元素包裹層的 class(combine 模式下無效)

細節

  • useScroll 取得捲動位移,再經 useVelocity 換算為速度,最後透過 useSpring 平滑,避免抖動並在停手後自然回正。
  • 傾斜方向隨滾動方向翻轉(向下為負角、向上為正角),速度越快傾斜與模糊越強,並在 maxVelocity 處達到上限。
  • maxBlur0 時不會套用 filter,可省去建立合成層的開銷。

可及性

  • 使用者系統開啟「減少動態效果」時,保留原始版面並移除所有速度驅動的傾斜與模糊。
  • 元件不攔截焦點或鍵盤行為,內容維持原本的語意與可讀性;範例中的捲動容器帶 tabIndexaria-label,可用鍵盤滾動。

On this page