跳到主要内容

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" }}>Check the floating boxes</p>
      <div
        ref={el}
        style={{
          position: "fixed",
          cursor: "move",
          zIndex: 10,
          touchAction: "none",
          padding: 10,
          border: "solid 1px",
          left: x,
          top: y,
        }}
      >
        {isDragging ? "Dragging!" : "👋 Drag me!"}
        <div>
          I am at {Math.round(x)}, {Math.round(y)}
        </div>
      </div>
    </div>
  );
};
结果
Loading...

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,
          });
        }}
      >
        Set Position
      </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 ? "Dragging!" : "👋 Drag me!"}
        <div style={{ whiteSpace: "nowrap" }}>
          I am at {Math.round(x)}, {Math.round(y)}
        </div>
      </div>
    </div>
  );
}
结果
Loading...

API

useDraggable

Returns

readonly [number, number, boolean, React.Dispatch<React.SetStateAction<Position>>]: 包含以下元素的元组:

  • x
  • y
  • 元素是否在拖动中
  • 设置元素的位置

Arguments

参数名描述类型默认值
targetdom对象BasicTarget<HTMLElement | SVGElement> (必填)-
options可选参数UseDraggableOptions | undefined-

UseDraggableOptions

参数名描述类型默认值
exact仅当直接单击元素时才开始拖动booleanfalse
preventDefault阻止默认事件booleanfalse
stopPropagation阻止事件冒泡booleanfalse
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;
}