Infinite Drag Canvas
無限拖曳平移的作品畫布,把卡片散佈於無邊界空間,可拖曳(含慣性)、鍵盤平移與一鍵回中。
載入預覽⋯
Playground
即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。
40
64
<InfiniteDragCanvas />
安裝
npx shadcn@latest add https://webberui.com/r/infinite-drag-canvas.json或在 components.json 設定 registries 後,改用 @webberui/infinite-drag-canvas 安裝。
安裝依賴後,從 registry JSON(/r/infinite-drag-canvas.json 的 files[0].content)複製 infinite-drag-canvas.tsx 原始碼到你的 components/ui/ 目錄:
npm install motion lucide-react clsx tailwind-merge使用
import {
InfiniteDragCanvas,
CanvasItem,
} from "@/components/ui/infinite-drag-canvas";
<InfiniteDragCanvas className="h-[400px]">
<CanvasItem x={-120} y={-40}>
<div className="rounded-xl border bg-white p-4 shadow">Aurora</div>
</CanvasItem>
<CanvasItem x={140} y={80}>
<div className="rounded-xl border bg-white p-4 shadow">Drift</div>
</CanvasItem>
</InfiniteDragCanvas>;畫布中心即世界座標原點 (0, 0);CanvasItem 以自身中心對齊所給的 x / y,並隨畫布一起平移。
Props
InfiniteDragCanvas
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
children | ReactNode | — | 放入 CanvasItem 子元件 |
offset | { x: number; y: number } | — | 受控平移位置,由外部狀態驅動 |
defaultOffset | { x: number; y: number } | { x: 0, y: 0 } | 非受控初始平移位置 |
onOffsetChange | (offset) => void | — | 平移變化時回報(拖曳/慣性/回中/鍵盤,座標取整) |
momentum | boolean | true | 放開後是否帶慣性滑行 |
showGrid | boolean | true | 是否顯示跟隨平移的點陣背景 |
gridSize | number | 40 | 點陣背景間距(px) |
showRecenter | boolean | true | 是否顯示內建「回到中心」按鈕 |
keyboardStep | number | 64 | 聚焦後方向鍵每次平移距離(px) |
className | string | — | 附加樣式(可用 h-* 覆寫畫布高度) |
CanvasItem
| Prop | 型別 | 預設值 | 說明 |
|---|---|---|---|
x | number | — | 世界座標 X(px),以畫布中心為原點 |
y | number | — | 世界座標 Y(px),以畫布中心為原點 |
children | ReactNode | — | 卡片內容 |
className | string | — | 附加樣式 |
細節
- 拖曳、觸控與慣性滑行由 Motion 內建
drag處理,無拖曳邊界,因此空間可無限延伸。 - 點陣背景以
gridSize取模平移,只需覆蓋視窗+一格即可製造無限重複的錯覺;點色使用currentColor,深淺色自動切換。 offset/defaultOffset支援受控與非受控雙模式:傳入offset時由外部狀態同步平移位置,未傳入時內部自理,並透過onOffsetChange回報。- 內建「回到中心」按鈕以 spring 平滑滑回
defaultOffset(或原點)。
可及性
- 畫布為
role="group"且可聚焦(tabIndex=0),帶說明用的aria-label。 - 聚焦後可用方向鍵平移、
Home鍵回到中心,方向鍵會阻止頁面捲動。 - 使用者系統開啟「減少動態效果」時,關閉慣性滑行,回中與鍵盤平移改為即時跳位(不影響 DOM 結構)。
- 拖曳進行中,
CanvasItem會停用指標事件,避免誤觸內部連結或選取文字。