Frontend Lab
← 回到所有效果
G11I101gsap

Draggable Cards

可拖曳卡片

難度 ★★★★★標籤 drag · draggable · inertia3 min read

效果簡述

卡片可被滑鼠 / 觸控拖曳。GSAP Draggable 是免費 plugin,比 framer-motion 的 drag 多了 inertia / hitTest / 進階回呼。但簡單拖曳的話 framer 也夠用。

拖我 · 限制邊界
卡片 A
卡片 B
卡片 C
預設|自由拖拉

Claude Code Prompt

💬 Claude Code Prompt
參考:I101 draggable cards
技術:gsap Draggable

具體行為:
- gsap.registerPlugin(Draggable)
- Draggable.create(el, { type: 'x,y', bounds: containerRef, edgeResistance: 0.65, inertia: true })
- 想要慣性的話需要 InertiaPlugin(付費);只用 Draggable 本身免費

限制:
- inertia 是付費功能,沒買就 false
- bounds 設定要嚴格,不然會拖出去找不回來
- 跟頁面滾動衝突時用 dragClickables: false

完整程式碼

DraggableCards.tsx
'use client'

import gsap from 'gsap'
import { Draggable } from 'gsap/Draggable'
import { useEffect, useRef } from 'react'

export function DraggableCards() {
const root = useRef<HTMLDivElement>(null)

useEffect(() => {
  gsap.registerPlugin(Draggable)
  const cards = root.current?.querySelectorAll<HTMLElement>('.card')
  if (!cards) return
  const inst: Draggable[] = []
  cards.forEach((c) => {
    inst.push(...Draggable.create(c, { type: 'x,y', bounds: root.current, edgeResistance: 0.65 }))
  })
  return () => inst.forEach((i) => i.kill())
}, [])

return (
  <div ref={root} className="relative h-72">
    <div className="card absolute h-20 w-28 bg-orange-500/30" />
  </div>
)
}

何時用

  • ✅ Kanban / 看板互動
  • ✅ 互動式拼貼 / mood board
  • ✅ 概念展示 / 玩心專案

何時別用

  • ❌ 卡片資訊重要、不想被打亂位置
  • ❌ 長列表(拖卡會跟滾動衝突)
  • ❌ 沒考慮 a11y 鍵盤操作的場景

我踩過的坑

  1. bounds 沒設拖到天荒地老:忘記 bounds 結果用戶拖到 -2000px 都還沒停。一定要 bounds: containerRef。

  2. inertia 是付費 plugin:免費版只能 type, bounds, edgeResistance。 想要丟出去再緩停得買 Club GreenSock。

  3. mobile 跟頁面滾動衝突:垂直拖卡時被頁面捲走。設定 allowEventDefault: false 或限制 type: 'x' 只能橫拖。

相關效果

搜尋

按 ⌘K 隨時開啟