WebberUI

Perspective Carousel

3D 透視輪播(coverflow 風格),支援拖曳翻頁、循環、自動輪播與受控/非受控雙模式。

載入預覽⋯

Playground

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

1200
45
120
2
0.12
<PerspectiveCarousel />

安裝

npx shadcn@latest add https://webberui.com/r/perspective-carousel.json

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

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

npm install motion lucide-react clsx tailwind-merge

使用

import { PerspectiveCarousel } from "@/components/ui/perspective-carousel";

const items = [
  { id: "a", content: <img src="/1.jpg" alt="" className="h-full w-full object-cover" /> },
  { id: "b", content: <img src="/2.jpg" alt="" className="h-full w-full object-cover" /> },
  { id: "c", content: <img src="/3.jpg" alt="" className="h-full w-full object-cover" /> },
];

<PerspectiveCarousel items={items} loop />

受控模式

傳入 indexonIndexChange 即進入受控模式,可與外部狀態(如指示點、縮圖列)同步:

const [active, setActive] = React.useState(0);

<PerspectiveCarousel items={items} index={active} onIndexChange={setActive} loop />

程式化操作

透過 ref 取得 next / prev / goTo

const ref = React.useRef<PerspectiveCarouselHandle>(null);

<PerspectiveCarousel ref={ref} items={items} />
<button onClick={() => ref.current?.next()}>下一張</button>

Props

Prop型別預設值說明
itemsPerspectiveCarouselItem[]投影片陣列,每項含 idcontent
indexnumber受控目前索引(0 起算),提供時由外部掌控
defaultIndexnumber0非受控初始索引
onIndexChange(index: number) => void索引變動時觸發
loopbooleanfalse是否循環(頭尾相接的環狀 3D 排列)
itemWidthnumber240投影片寬度(px)
itemHeightnumber320投影片高度(px)
visiblenumber2每側可見的鄰片數量
perspectivenumber1200CSS 透視距離(px),越小透視越強
rotatenumber45鄰片繞 Y 軸旋轉角度(deg)
depthnumber120每階往後推的 Z 位移(px)
spreadnumberitemWidth * 0.6每階水平間距(px)
scaleStepnumber0.12每階縮小比例
autoplaybooleanfalse自動輪播(減少動態時停用)
autoplayIntervalnumber3500自動輪播間隔(ms)
showArrowsbooleantrue是否顯示左右箭頭
velocityThresholdnumber320觸發翻頁的甩動速度閾值(px/s)
ariaLabelstring"3D 透視輪播"輪播區的無障礙標籤

型別

interface PerspectiveCarouselItem {
  id: string | number;
  content: React.ReactNode;
}

interface PerspectiveCarouselHandle {
  next: () => void;
  prev: () => void;
  goTo: (index: number) => void;
}

細節

  • 純 CSS 3D transform(perspective + rotateY + translateZ)打造 coverflow 透視,未依賴任何 WebGL 套件。
  • 所有投影片共用一個浮點位置 motion value,中心到兩側的位移、旋轉、縮放、透明度與壓暗皆由該值連續映射,拖曳過程即時跟手。
  • 拖曳放開時依落點四捨五入翻頁,甩動速度超過 velocityThreshold 則往甩動方向再進一張。
  • loop 開啟時採最短環狀路徑落定,並在動畫結束後將位置正規化,長時間輪播不會累積漂移。

可及性

  • 輪播容器帶 role="group"aria-roledescription="輪播" 與可聚焦的 tabIndex,方向鍵可翻頁,Home / End 直達首末張。
  • 目前張數以 aria-live="polite" 的隱藏區域朗讀(「第 N 張,共 M 張」);非當前投影片標記 aria-hidden
  • 左右箭頭為原生 button,附 aria-label 並在到達邊界(非循環)時 disabled
  • 使用者系統開啟「減少動態效果」時,停用拖曳與自動輪播,翻頁改為即時切換不含補間動畫。
  • 指標懸停或焦點進入輪播區時自動暫停自動輪播。

On this page