輪播

放射畫廊

圖片從中心爆開排成一圈後緩慢公轉,點選任一張飛到中央放大、其餘縮回環上,支援鍵盤切換。

把一組圖片排成會呼吸的圓環。進入視窗時每張卡片從中心以彈簧錯開爆開到環上,接著整圈緩慢公轉,滑鼠移上或鍵盤聚焦時平順減速停下。點選任一張,它會以共享版面動畫飛到中央放大、下方淡入說明,其餘卡片縮小變淡留在環上;再點中央、按 Esc 或點空白處就飛回原位。每張卡片可以是圖片網址,也可以是任意 React 節點(例如 CSS 漸層畫的圖)。選取狀態支援受控/非受控雙模式。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add radial-burst-gallery

還沒有專案,或安裝遇到問題?看快速開始 →

Playground

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

180
40
180
96
編輯中的呼叫預設屬性
<RadialBurstGallery/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

安裝

npx webberui@latest add https://webberui.com/r/radial-burst-gallery.json

或在 components.json 設定 registries 後,改用 @webberui/radial-burst-gallery 安裝。

使用

import { RadialBurstGallery } from "@/components/ui/radial-burst-gallery";

<RadialBurstGallery
  images={[
    { src: "/photos/ridge.jpg", alt: "霧中的稜線", caption: "霧中的稜線|合歡山" },
    { src: "/photos/tide.jpg", alt: "退潮之後", caption: "退潮之後|高美濕地" },
    { src: "/photos/blue.jpg", alt: "藍色時刻", caption: "藍色時刻|北海岸" },
  ]}
  radius={180}
  period={40}
  onSelectedChange={(index) => console.log("選取", index)}
/>

Props

Prop型別預設值說明
imagesRadialBurstGalleryImage[]—圖片清單,依陣列順序從正上方順時針排成一圈
radiusnumber180環的半徑(px);容器太窄時自動縮成 min(radius, 容器寬/2 − 卡寬)
periodnumber40環公轉一圈的秒數;未提供時讀取 CSS 變數 --wb-rbg-period,再退回 40 秒
stiffnessnumber180爆開與飛行彈簧的剛性,數字越大越俐落
cardWidthnumber96環上卡片寬度(px)
aspectstring"3/4"卡片寬高比,格式為「寬/高」
centerSizenumber260選取後中央卡片的寬度(px);容器太窄時自動縮小
tiltToCenterbooleanfalse讓環上卡片的頂端朝外(隨角度旋轉),預設保持正立
selectedIndexnumber | null—受控的選取索引(null 表示未選取);未提供時由元件內部管理
defaultSelectedIndexnumber | nullnull非受控模式的初始選取索引
onSelectedChange(index: number | null) => void—選取變動時回呼,取消選取時參數為 null
pauseOnHoverbooleantrue滑鼠移到卡片上時暫停公轉
classNamestring—透傳到最外層容器

RadialBurstGalleryImage

欄位型別預設值說明
srcstring—圖片網址;與 node 擇一,兩者都給時以 node 為準
altstring—替代文字,同時作為卡片按鈕的 aria-label(必填)
nodeReactNode—自訂內容,例如 CSS 漸層畫出的圖
captionReactNode—選取後顯示在中央卡片下方的說明

細節

  • 幾何:n 張卡片平均分布在圓上,第 i 張的角度是 i/n × 360° 加上環的旋轉角,從正上方順時針排列;卡片只平移不旋轉,開啟 tiltToCenter 才讓頂端朝外。
  • 爆開:第一次進入視窗時,每張卡片從中心以 scale 0.3、透明度 0 出發,以彈簧(stiffness 預設 180、damping 18)飛到環上,每張錯開 50ms;彈簧會略微衝出環外再回彈。之後捲走再回來不會重播。
  • 公轉:以 requestAnimationFrame 依 period 推進旋轉角;滑鼠移到卡片上、鍵盤焦點在畫廊內或有卡片被選取時,速度在 150ms 內漸變到 0,不會瞬停。畫廊離開視窗時停止動畫迴圈。
  • 節奏變數:不傳 period 時,元件讀取根元素上的 --wb-rbg-period(可寫 40s 或 40000ms),方便以全域樣式統一調整;明確傳入的 period 優先。
  • 選取:被選中的卡片以 Motion 的 layoutId(以 useId 為前綴,同頁多個畫廊不互相干擾)飛到中央放大到 centerSize;其餘卡片縮到 0.8、透明度 0.6。環上卡片以 left/top 定位而非 transform,讓共享版面動畫量到正確的起點。
  • 窄容器:以 ResizeObserver 量測容器寬,半徑自動縮成 min(radius, 容器寬/2 − 卡寬),中央卡片寬度不超過容器寬減 32px。

可及性

  • 外層為 role="group"、aria-roledescription="畫廊";每張卡片是 type="button",aria-label 取自 alt
  • 採 roving tabindex:Tab 只停在一張卡片上,←/→(與 ↑/↓)依環順序移動焦點,Home/End 跳到第一張與最後一張;焦點在畫廊內時環暫停公轉
  • Enter/Space 選取,焦點移到中央卡片;Esc、再按一次中央卡片或點空白處取消選取,焦點回到原本那張卡片
  • 選取時 aria-live="polite" 區域宣告「第幾張,共幾張」與 caption(沒有 caption 時讀 alt)
  • 使用者系統開啟「減少動態效果」時,不爆開也不公轉,卡片直接靜態排成一圈;選取改為中央交叉淡入,沒有飛行動畫