87 lines
1.7 KiB
JavaScript
87 lines
1.7 KiB
JavaScript
import React, { useState, useRef, useEffect } from 'react';
|
|
import { Modal } from 'antd';
|
|
|
|
const DraggableModal = ({
|
|
open,
|
|
onCancel,
|
|
title,
|
|
width = 420,
|
|
children,
|
|
...props
|
|
}) => {
|
|
const [position, setPosition] = useState({ x: 0, y: 0 });
|
|
const [isDragging, setIsDragging] = useState(false);
|
|
const startPos = useRef({ x: 0, y: 0 });
|
|
|
|
// 打开时重置位置
|
|
useEffect(() => {
|
|
if (open) {
|
|
setPosition({ x: 0, y: 0 });
|
|
}
|
|
}, [open]);
|
|
|
|
// 拖拽开始
|
|
const handleMouseDown = (e) => {
|
|
startPos.current = {
|
|
x: e.clientX - position.x,
|
|
y: e.clientY - position.y,
|
|
};
|
|
setIsDragging(true);
|
|
};
|
|
|
|
// 拖拽中
|
|
useEffect(() => {
|
|
const handleMouseMove = (e) => {
|
|
if (!isDragging) return;
|
|
setPosition({
|
|
x: e.clientX - startPos.current.x,
|
|
y: e.clientY - startPos.current.y,
|
|
});
|
|
};
|
|
|
|
const handleMouseUp = () => {
|
|
setIsDragging(false);
|
|
};
|
|
|
|
if (isDragging) {
|
|
document.addEventListener('mousemove', handleMouseMove);
|
|
document.addEventListener('mouseup', handleMouseUp);
|
|
}
|
|
|
|
return () => {
|
|
document.removeEventListener('mousemove', handleMouseMove);
|
|
document.removeEventListener('mouseup', handleMouseUp);
|
|
};
|
|
}, [isDragging]);
|
|
|
|
return (
|
|
<Modal
|
|
open={open}
|
|
onCancel={onCancel}
|
|
footer={null}
|
|
width={width}
|
|
mask={false}
|
|
style={{
|
|
transform: `translate(${position.x}px, ${position.y}px)`,
|
|
transition: isDragging ? 'none' : 'transform 0.2s ease',
|
|
}}
|
|
title={
|
|
<div
|
|
onMouseDown={handleMouseDown}
|
|
style={{
|
|
cursor: isDragging ? 'grabbing' : 'grab',
|
|
userSelect: 'none',
|
|
}}
|
|
>
|
|
{title}
|
|
</div>
|
|
}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</Modal>
|
|
);
|
|
};
|
|
|
|
export default DraggableModal;
|