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
);
};
页面拖拽框选
于 2025-04-14 17:32:45 首次发布