Files
web-Iot/src/components/DraggableModal.jsx
2026-05-09 16:44:39 +08:00

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;