页面拖拽框选

import { Ref, useEffect, useRef, useState } from 'react';
import { MOUSETYPE } from '@/pages/task/constants';
import { isContain } from '@/pages/task/core';

interface IProps {
  containIdStr: string;
  targetClassNameStr: string;
  clickBack: (id: string) => void;
  effect?: any;
  bottomRef?: any;
}
export const useDragSelect = (props: IProps) => {
  const { targetClassNameStr, containIdStr, clickBack, effect, bottomRef } = props;
  const [selectIds, setSelectIds] = useState<string[]>([]);
  const isDragging = useRef(false);
  const mouseType = useRef<MOUSETYPE>('click');

  const reset = () => {
    mouseType.current = 'click';
    isDragging.current = false;
    setSelectIds([]);
  };

  useEffect(() => {
    reset();
  }, [effect]);
  const onClickSelect = (id: string, e: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
    if (e?.shiftKey) {
      mouseType.current = 'shift';
      setSelectIds((pre) => {
        if (pre?.some((item) => item === id)) {
          return pre?.filter((item) => item !== id);
        } else return pre.concat(id);
      });
    } else {
      mouseType.current = 'click';
      setSelectIds([]);
      clickBack?.(id);
    }
  };
  const dragSelect = () => {
    let startX, startY, endX, endY, selectionRect;
    const dom = document.getElementById(containIdStr);
    if (dom && bottomRef?.current) {
      const { top, left } = dom.getBoundingClientRect();
      dom?.addEventListener('mousedown', function (e) {
        if (e.button === 0) {
          // 确保是鼠标左键点击开始拖拽选择框
          isDragging.current = true;
          startX = e.clientX - left;
          startY = e.clientY - top + dom.scrollTop;
          selectionRect = document.createElement('div'); // 创建选择框元素
          selectionRect.style.position = 'absolute';
          // selectionRect.style.border = '2px dashed #000'; // 设置选择框样式
          dom.appendChild(selectionRect); // 将选择框添加到DOM中
        }
      });
      dom?.addEventListener('mousemove', function (e) {
        if (isDragging.current && !e?.shiftKey) {
          if (mouseType.current === 'up') {
            setSelectIds([]);
          }
          mouseType.current = 'move';
          endX = e.clientX - left;
          endY = e.clientY - top + dom.scrollTop;
          selectionRect.style.left = `${Math.min(startX, endX)}px`; // 设置选择框位置和大小
          selectionRect.style.top = `${Math.min(startY, endY)}px`;
          selectionRect.style.width = `${Math.abs(endX - startX)}px`; // 设置选择框大小(宽度)
          selectionRect.style.height = `${Math.abs(endY - startY)}px`; // 设置选择框大小(高度)
          // selectionRect.style.zIndex = -1;
          selectionRect.style.background = 'rgba(61, 94, 255, 0.1)';
          selectionRect.style.border = '0.5px solid #3D5EFF';
          const images = document.querySelectorAll(targetClassNameStr);
          images?.forEach((element) => {
            const dataId = element.getAttribute('data-id');
            if (isContain(element as HTMLElement, selectionRect) && dataId) {
              setSelectIds((pre) => Array.from(new Set([...pre, dataId as string])));
            } else {
              setSelectIds((pre) => pre?.filter((item) => item !== dataId));
            }
          });
        }
      });
      document.addEventListener('mouseup', (e) => {
        isDragging.current = false;
        if (mouseType.current === 'move' && !e?.shiftKey) {
          mouseType.current = 'up';
          selectionRect?.remove?.();
        } else if (mouseType.current === 'up' && !e?.shiftKey && !bottomRef?.current?.contains(e?.target)) {
          setSelectIds([]);
        } else if (mouseType.current === 'shift' && !e?.shiftKey && !bottomRef?.current?.contains(e?.target)) {
          setSelectIds([]);
        }
      });
    }
  };

  useEffect(() => {
    dragSelect();
  }, [bottomRef]);

  return {
    onClickSelect,
    selectIds,
    reset,
    onChangeSelectIds: (ids: string[]) => setSelectIds(ids),
  };
};

export const isContain = (el: HTMLElement, dom: HTMLElement) => {
  const rect1 = dom.getBoundingClientRect();
  const rect2 = el.getBoundingClientRect();
  return !(
    rect1.left + rect1.width < rect2.left ||
    rect2.left + rect2.width < rect1.left ||
    rect1.top + rect1.height < rect2.top ||
    rect2.top + rect2.height < rect1.top
  );
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值