輪播

速度銜接場景滑軌

以拖曳初速銜接切換的場景卡滑軌:放手時的速度直接成為下一張的彈簧初速,底部膠囊指示條隨進度伸縮。

這是 WebberUI Pro 元件

下方的安裝指令需要授權才能執行,未授權時會回 401。

怎麼安裝 Pro 元件 →查看方案 →

一條水平場景軌道:每張場景卡可放任意內容,左右拖曳或點底部指示條切換。重點在放手的那一刻——拖曳速度會原封交給換頁彈簧當初速,快甩就快速到位,慢推就緩緩滑過去,動作從手指到落定是一條連續的速度曲線。拖曳中底部膠囊指示條依進度一伸一縮,場景卡越靠近中央越清楚。適合功能導覽、新手引導、產品場景展示。

把這個效果裝進你的專案

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

npx webberui@latest add "https://webberui.com/r/velocity-scene-slider.json?t=<安裝 token>"

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

Playground

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

260
30
400
編輯中的呼叫預設屬性
<VelocitySceneSlider/>

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

安裝

npx webberui@latest add "https://webberui.com/r/velocity-scene-slider.json?t=<安裝 token>"

或在 components.json 設定 registries 後,改用 @webberui/velocity-scene-slider 安裝。

使用

import {
  VelocitySceneSlider,
  type VelocityScene,
} from "@/components/ui/velocity-scene-slider";

const scenes: VelocityScene[] = [
  { id: "inbox", label: "收件匣整理", content: <InboxScene /> },
  { id: "schedule", label: "排程建議", content: <ScheduleScene /> },
  { id: "board", label: "團隊看板", content: <BoardScene /> },
];

export function Tour() {
  const [index, setIndex] = React.useState(0);
  return (
    <VelocitySceneSlider
      scenes={scenes}
      index={index}
      onIndexChange={setIndex}
      onRelease={({ velocity }) => console.log(`${Math.round(velocity)} px/s`)}
    />
  );
}

Props

Prop型別預設值說明
scenesVelocityScene[]—場景卡清單,建議 3–7 張
indexnumber—受控模式的目前場景索引;未提供時由元件內部管理
defaultIndexnumber0非受控模式的初始場景索引
onIndexChange(index: number) => void—場景切換時回呼(拖曳、指示條、鍵盤皆會回報)
onRelease(info: VelocitySceneRelease) => void—拖曳放手時回呼,帶放手速度、位移與目標索引
stiffnessnumber260換頁彈簧剛性,越高越快到位
dampingnumber30換頁彈簧阻尼,越低越容易回彈過頭
velocityThresholdnumber400放手速度超過此值(px/s)即換頁,不論位移多寡
loopbooleanfalse到頭/到尾時是否環繞至另一端
showIndicatorbooleantrue是否顯示底部膠囊指示條
ariaLabelstring"場景輪播"整個輪播區域的無障礙標籤
classNamestring—透傳到最外層容器

VelocityScene

欄位型別預設值說明
idstring—場景唯一識別碼
labelstring—場景名稱,用於指示條按鈕與螢幕閱讀器朗讀
contentReact.ReactNode—場景卡內容

VelocitySceneRelease

欄位型別預設值說明
velocitynumber—放手當下的水平速度(px/s,向左為負)
offsetnumber—拖曳期間的水平位移(px)
indexnumber—放手後要前往的場景索引

CSS 變數

變數預設值說明
--wb-velocity-scene-indicator-duration240ms指示條膠囊寬度與顏色的過渡時間
--wb-velocity-scene-gap24px場景卡之間的間距;步距會從實際版面量測,覆寫後拖曳與定位自動跟上

細節

  • 速度銜接:放手時讀取拖曳速度,原封交給換頁彈簧的 velocity。同樣的 stiffness/damping,快甩與慢推的到位時間與手感因此不同;點指示條或用鍵盤換頁時初速為 0
  • 換頁判定:速度優先——放手速度絕對值超過 velocityThreshold 就往速度方向換一頁;否則位移超過卡寬 25% 才換頁,未達則彈回原位
  • 環繞:loop 開啟時從最後一張往後甩會回到第一張。這時軌道要往反方向長距離移動,沿用放手速度會先朝錯的方向衝出去,所以環繞時初速改為 0
  • 指示條:平時作用中的膠囊 28px、其餘 8px,以 CSS 過渡伸縮;拖曳中改依連續進度逐幀插值相鄰兩顆的寬度,呈現被拉長的感覺
  • 場景卡:依與中央的距離插值,縮放 0.94→1、透明度 0.6→1;卡寬為容器的 82%,左右露出鄰卡一角
  • 受控模式:父層若不接受 onIndexChange 回報的新索引,軌道會以彈簧回到原本的場景

可及性

  • 根元素為 role="region"、aria-roledescription="carousel",可用 Tab 聚焦,帶 focus-visible 外框
  • 每張場景卡為 role="group"、aria-roledescription="slide",aria-label 為「第 n 張,共 N 張:名稱」;不在中央的卡片設為 inert,不可聚焦也不會被朗讀
  • 聚焦後可用左右方向鍵換頁,Home/End 跳到第一張/最後一張
  • 指示條為 role="tablist",每顆膠囊是帶 aria-selected 與 aria-controls 的 type="button" 分頁按鈕,採 roving tabindex,方向鍵移動時焦點跟著走
  • 以 aria-live="polite" 宣告目前場景
  • 使用者系統開啟「減少動態效果」時,停用拖曳放手後的彈簧慣性,換頁改為合計 150ms 的淡出淡入;指示條膠囊直接跳到目標寬度,不做過渡