Waypoint Stage
把各段內容以座標擺在超大畫布上,捲動驅動攝影機沿航點路徑平移、縮放、旋轉,完成 Prezi 式空間敘事。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
1
0.25
0.72
<WaypointStage />
安裝
npx shadcn@latest add https://webberui.com/r/waypoint-stage.json或在 components.json 設定 registries 後,改用 @webberui/waypoint-stage 安裝。
安裝依賴後,從 registry JSON(/r/waypoint-stage.json 的 files[0].content)複製 waypoint-stage.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
以 WaypointStage 包住若干 Waypoint,每個航點用 x / y 宣告它在畫布上的座標,用 zoom / rotate 決定攝影機抵達時的構圖。捲動即驅動攝影機依序飛抵。
import { Waypoint, WaypointStage } from "@/components/ui/waypoint-stage";
<WaypointStage>
<Waypoint x={0} y={0} label="開場">
<h2 className="text-4xl font-bold">歡迎</h2>
</Waypoint>
<Waypoint x={800} y={-320} zoom={1.4} rotate={-8} label="重點">
<p className="max-w-sm">飛到這裡放大、傾斜構圖。</p>
</Waypoint>
<Waypoint x={-360} y={420} zoom={1.2} rotate={6} label="收尾">
<p>再轉到另一處。</p>
</Waypoint>
</WaypointStage>預設以視窗為捲動容器並以 h-screen 釘住舞台。若放在巢狀的 overflow-y-auto 容器內,將該容器 ref 傳入 container,並以 stageClassName 覆寫舞台高度為容器可視高度(如 h-[300px])。
Props
WaypointStage
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 放入 Waypoint 子元件 |
pace | number | 1 | 每段航程的捲動長度(以釘住舞台高度為單位) |
dwell | number | 0.25 | 抵達每個航點後停留的比例(0–0.49) |
zoomOut | number | 0.72 | 兩航點間攝影機拉遠的程度(1 表不拉遠) |
smooth | boolean | true | 是否以 spring 平滑運鏡 |
showPath | boolean | true | 是否描繪連接航點的虛線路徑 |
showNav | boolean | true | 是否顯示可點擊跳轉的導覽點 |
grid | boolean | true | 是否鋪上淡點陣底紋 |
container | RefObject<HTMLElement | null> | — | 巢狀捲動容器的 ref;預設以視窗為捲動容器 |
stageClassName | string | "h-screen" | 釘住的舞台容器高度 |
className | string | — | 外層捲動軌道容器 |
Waypoint
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
x | number | — | 航點中心在畫布上的 X 座標(px) |
y | number | — | 航點中心在畫布上的 Y 座標(px) |
zoom | number | 1 | 攝影機抵達時的縮放;>1 放大、<1 縮小 |
rotate | number | 0 | 此航點在畫布上的旋轉角度(度);抵達時會轉正 |
label | string | — | 導覽點與輔助科技用的名稱 |
children | ReactNode | — | 航點內容 |
細節
- 攝影機以純 CSS
transform(translate+scale+rotate,原點錨定視口中心)實作,無需 WebGL。內容以中心對齊各自座標,攝影機飛抵時剛好轉正並置中。 - 過場採「先拉遠、再推進」的關鍵影格;
zoomOut控制中途拉遠幅度,dwell控制抵達後的駐留長度。 - 軌道高度依航點數量與
pace自動換算:航點越多、pace越大,捲動距離越長、運鏡越從容。 - 巢狀捲動時務必同時傳入
container與相符的stageClassName,useScroll才能正確以該容器為捲動來源。
可及性
- 使用者系統開啟「減少動態效果」時,攝影機運鏡整組停用,改把各航點依序排成靜態縱向段落,避免大範圍縮放與旋轉造成不適。
- 導覽點為可聚焦的按鈕,帶
aria-label與aria-current,可用鍵盤操作並平滑跳轉至對應航點。 - 舞台另附一份
sr-only的順序清單供輔助科技朗讀,與動畫視覺解耦。 ResizeObserver、spring 皆在卸載時由 Motion 與 effect 清理。