useDraggable
元素拖动
Usage
Fixed Demo
即時編輯器
function Demo() { const el = useRef<HTMLDivElement>(null); const [initialValue, setInitialValue] = useState({ x: 200 / 2.2, y: 120 }); useEffect(() => { setInitialValue({ x: window.innerWidth / 2.2, y: 120 }); }, []); const [x, y, isDragging] = useDraggable(el, { initialValue, preventDefault: true, }); return ( <div> <p style={{ textAlign: "center" }}>查看浮動方框</p> <div ref={el} style={{ position: "fixed", cursor: "move", zIndex: 10, touchAction: "none", padding: 10, border: "solid 1px", left: x, top: y, }} > {isDragging ? "正在拖拽!" : "👋 拖拽我!"} <div> 我在 {Math.round(x)}, {Math.round(y)} </div> </div> </div> ); };
結果
查看浮動方框
👋 拖拽我!
我在 655, 120
Relative Demo
即時編輯器
function Demo() { const el = useRef<HTMLDivElement>(null); const scope = useRef<HTMLDivElement>(null); const initialValue = { x: 200 / 2.2, y: 120 }; const [x, y, isDragging, setPosition] = useDraggable(el, { initialValue, preventDefault: true, containerElement: scope, }); return ( <div ref={scope} style={{ width: 500, height: 500, border: "1px solid blue", position: "relative", }} > <button style={{ textAlign: "center" }} onClick={() => { setPosition({ x: 250, y: 250, }); }} > 設定位置 </button> <div ref={el} style={{ position: "absolute", cursor: "move", zIndex: 10, touchAction: "none", padding: 10, border: "solid 1px", left: x, top: y, whiteSpace: "nowrap", }} > {isDragging ? "正在拖拽!" : "👋 拖拽我!"} <div style={{ whiteSpace: "nowrap" }}> 我在 {Math.round(x)}, {Math.round(y)} </div> </div> </div> ); }
結果
👋 拖拽我!
我在 91, 120
API
useDraggable
Returns
readonly [number, number, boolean, React.Dispatch<React.SetStateAction<Position>>]: 包含以下元素的元組:
- x
- y
- 元素是否在拖動中
- 設定元素的位置
Arguments
| 參數名 | 描述 | 類型 | 預設值 |
|---|---|---|---|
| target | dom对象 | BasicTarget<HTMLElement | SVGElement> (必填) | - |
| options | 可选参数 | UseDraggableOptions | undefined | - |
UseDraggableOptions
| 參數名 | 描述 | 類型 | 預設值 |
|---|---|---|---|
| exact | 仅当直接单击元素时才开始拖动 | boolean | false |
| preventDefault | 阻止默认事件 | boolean | false |
| stopPropagation | 阻止事件冒泡 | boolean | false |
| draggingElement | 将“pointermove”和“pointerup”事件附加到的dom元素 | BasicTarget<HTMLElement | SVGElement> | window |
| containerElement | 设置拖拽容器边界 | BasicTarget<HTMLElement | SVGAElement> | undefined |
| handle | 触发拖动事件的dom元素 | RefObject<HTMLElement | SVGElement> | target |
| pointerTypes | 监听的事件类型 | PointerType[] | ['mouse', 'touch', 'pen'] |
| initialValue | 初始的元素位置 | Position | { x: 0, y: 0 } |
| onStart | 拖动开始时的回调。 返回“false”以防止拖动 | (position: Position, event: PointerEvent) => void | false | - |
| onMove | 拖动时候的回调 | (position: Position, event: PointerEvent) => void | - |
| onEnd | 拖动结束的回调 | (position: Position, event: PointerEvent) => void | - |
BasicTarget
export type BasicTarget<T extends TargetType = Element> = (() => TargetValue<T>) | TargetValue<T> | MutableRefObject<TargetValue<T>>;
TargetValue
type TargetValue<T> = T | undefined | null;
TargetType
type TargetType = HTMLElement | Element | Window | Document | EventTarget;
PointerType
export type PointerType = 'mouse' | 'touch' | 'pen';
Position
export interface Position {
x: number;
y: number;
}