wujingjing
2025-01-19 1a20b21d285bc008f6a45fad132bc808a377f853
src/hooks/useDrag.ts
@@ -1,16 +1,38 @@
import type { Ref } from 'vue';
import { computed, ref } from 'vue';
export type UseDragOptions = {
   target: HTMLElement;
   onDrag: (e: MouseEvent) => void;
   onDragEnd: (e: MouseEvent) => void;
   /**
    * 拖拽手柄元素的选择器
    */
   handle?: string | HTMLElement | Ref<HTMLElement>;
};
export const useDrag = () => {
const getHandleElement = (handle: string | HTMLElement | Ref<HTMLElement>) => {
   if (!handle) return null;
   if (typeof handle === 'string') {
      return document.querySelector(handle);
   } else if (handle instanceof HTMLElement) {
      return handle;
   } else if (typeof handle === 'object' && 'value' in handle) {
      return handle.value;
   }
   return null;
};
export const useDrag = (options: UseDragOptions = {}) => {
   const { handle } = options;
   const isDragging = ref(false);
   const startPos = ref({ x: 0, y: 0 });
   const offset = ref({ x: 0, y: 0 });
   const startDrag = (e: MouseEvent) => {
      // 如果设置了handle,则判断事件源是否是handle元素或其子元素
      if (handle) {
         const handleElement = getHandleElement(handle);
         if (!handleElement?.contains(e.target as Node)) {
            return;
         }
      }
      isDragging.value = true;
      startPos.value = {
         x: e.clientX - offset.value.x,
@@ -35,19 +57,31 @@
      document.addEventListener('mousemove', handleMouseMove);
      document.addEventListener('mouseup', handleMouseUp);
   };
   const handleStyle = computed(() => {
      return handle
         ? {
               cursor: isDragging.value ? 'grabbing' : 'grab',
           }
         : {};
   });
   const style = computed(
      () =>
         ({
            position: 'absolute',
            transform: `translate(${offset.value.x}px, ${offset.value.y}px)`,
            cursor: isDragging.value ? 'grabbing' : 'grab',
            ...(handle
               ? {}
               : {
                     cursor: isDragging.value ? 'grabbing' : 'grab',
                 }),
         } as any)
   );
   return {
      isDragging,
      startDrag,
      style,
      handleStyle,
   };
};