ClipPath Carousel
以 clip-path 揭示過場的輪播,內建擦除、光圈、對角、方框四款樣式,支援拖曳、自動播放與受控/非受控雙模式。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
0.6
<ClippathCarousel />
安裝
npx shadcn@latest add https://webberui.com/r/clippath-carousel.json或在 components.json 設定 registries 後,改用 @webberui/clippath-carousel 安裝。
安裝依賴後,從 registry JSON(/r/clippath-carousel.json 的 files[0].content)複製 clippath-carousel.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion clsx tailwind-merge lucide-react使用
每個直接子節點就是一張投影片,第一項為初始畫面。切換時,進場投影片會以 clip-path 從收合狀態揭示到全開,覆蓋在離場投影片之上。
import { ClipPathCarousel } from "@/components/ui/clippath-carousel";
<ClipPathCarousel variant="iris">
<div className="flex h-full items-center justify-center bg-sky-500">一</div>
<div className="flex h-full items-center justify-center bg-rose-500">二</div>
<div className="flex h-full items-center justify-center bg-emerald-500">三</div>
</ClipPathCarousel>;揭示樣式
variant 提供四款單一 clip-path 過場:
wipe:依方向自左或右邊緣擦除展開iris:圓形光圈自中心向外擴張diagonal:三角形自左上(下一張)或右下(上一張)角落斜向展開box:矩形自中心向四周展開
自動播放
設定 autoPlay 與 interval;滑鼠移入、鍵盤聚焦或分頁切到背景時會自動暫停。
<ClipPathCarousel autoPlay interval={3000}>
{/* ... */}
</ClipPathCarousel>程式化控制
透過 ref 取得 next() / prev() / goTo()。
import {
ClipPathCarousel,
type ClipPathCarouselHandle,
} from "@/components/ui/clippath-carousel";
const ref = React.useRef<ClipPathCarouselHandle>(null);
<ClipPathCarousel ref={ref}>{/* ... */}</ClipPathCarousel>;
<button onClick={() => ref.current?.next()}>下一張</button>;受控模式
傳入 index 與 onIndexChange 即進入受控模式;否則用 defaultIndex 走非受控。
const [index, setIndex] = React.useState(0);
<ClipPathCarousel index={index} onIndexChange={setIndex}>
{/* ... */}
</ClipPathCarousel>;Props
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | React.ReactNode | — | 每個直接子節點為一張投影片 |
variant | "wipe" | "iris" | "diagonal" | "box" | "wipe" | clip-path 揭示樣式 |
index | number | — | 受控的目前索引 |
defaultIndex | number | 0 | 非受控模式的初始索引 |
onIndexChange | (index: number) => void | — | 目前索引變更時觸發 |
loop | boolean | true | 到底/到頭是否循環 |
duration | number | 0.6 | 揭示動畫時長(秒) |
autoPlay | boolean | false | 是否自動輪播 |
interval | number | 4000 | 自動輪播間隔(毫秒) |
showArrows | boolean | true | 是否顯示左右箭頭 |
showIndicators | boolean | true | 是否顯示底部指示點 |
enableDrag | boolean | true | 是否允許拖曳/滑動切換 |
aspectRatio | string | "16 / 9" | 容器長寬比(CSS aspect-ratio 值) |
slideClassName | string | — | 套用到每張投影片外層 |
className | string | — | 套用到最外層容器 |
ref 會取得 ClipPathCarouselHandle:next()、prev()、goTo(index)。
細節
- 切換時同時渲染離場與進場兩張投影片:離場者靜置於底層,進場者以
clip-path疊在其上揭示,動畫結束後即卸載離場張。 - 過場開啟在 paint 前(layout effect)進行,避免出現整張直接顯示的閃爍。
- 拖曳(或觸控滑動)超過位移或甩動速度閾值即切換到上/下一張,未達門檻則彈回原位。
- 受控(
index+onIndexChange)與非受控(defaultIndex)雙模式;子節點數量變動時,非受控索引會自動夾回合法範圍。
可及性
- 容器帶
role="group"與aria-roledescription="輪播",並以aria-live區域朗讀目前張數。 - 檢視區可聚焦,方向鍵左/右對應上一張/下一張;箭頭與指示點皆為具
aria-label的按鈕。 - 使用者系統開啟「減少動態效果」時,停用 clip-path 揭示與拖曳,切換改為即時替換,不做大幅度動態。