(含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
·
原生写法
// 封装组件
import React, { useState, useRef } from 'react';
const DraggableModal = ({ children }) => {
const [position, setPosition] = useState({ x: 0, y: 0 });
const modalRef = useRef(null);
const handleMouseDown = (e) => {
const modal = modalRef.current;
const startX = e.clientX - modal.offsetLeft;
const startY = e.clientY - modal.offsetTop;
const handleMouseMove = (e) => {
setPosition({
x: e.clientX - startX,
y: e.clientY - startY
});
};
const handleMouseUp = () => {
document.removeEventListener('mousemove', handleMouseMove);
document.removeEventListener('mouseup', handleMouseUp);
};
document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('mouseup', handleMouseUp);
};
return (
<div
ref={modalRef}
style={{ position: 'absolute', left: position.x, top: position.y }}
>
<div style={{ cursor: 'move' }} onMouseDown={handleMouseDown}>
Drag Me
</div>
{children}
</div>
);
};
export default DraggableModal;
// 使用
<DraggableModal>
<ModalContent />
</DraggableModal>
使用库并处理拖动和点击事件重叠问题
// 使用库实现功能
你可以使用react-draggable库来实现这个功能。首先安装react-draggable库:
```
npm install react-draggable
```
然后在你的组件中引入react-draggable库,并使用它来包裹你想要添加可拖动功能的按钮:
```jsx
import React from 'react';
import Draggable from 'react-draggable';
const DraggableButton = () => {
let isDragging = false;
const handleDrag = () => {
isDragging = true;
};
const handleStop = () => {
console.log('handleStop');
// 触发 onStop 后会触发 onClick,加个 setTimeout 是为了让修改不“马上”发生,导致 handleClick 拿到的不是预期的结果
setTimeout(() => (isDragging = false), 0);
};
const handleClick = () => {
console.log('handleClick');
if (isDragging) {
return;
}
console.log('啊,我被 click 了');
};
return (
<Draggable onDrag={handleDrag} onStop={handleStop}>
<button onClick={handleClick} style={{ position: 'fixed', bottom: 0, right: 0 }}>可拖动按钮</button>
</Draggable>
);
}
export default DraggableButton;
解决库和Antd Tooltip配置使用无法拖动
可以尝试使用`react-draggable`的`handle`属性来指定拖动的句柄,避免事件冲突。
示例代码如下:
<Draggable handle=".drag-handle">
<div>
<Button className="drag-handle">
Hover me
<Tooltip title="Tooltip text">
<QuestionCircleOutlined />
</Tooltip>
</Button>
</div>
</Draggable>
移动端或PC端如何判断react-draggable包裹的组件时点击还是移动(含移动位置判断),用reack hook代码实现
// 判断是否点击还是移动
import React, { useState } from 'react';
import Draggable from 'react-draggable';
const DraggableComponent = () => {
const [isDragging, setIsDragging] = useState(false);
const handleTouchStart = (e) => {
setIsDragging(false);
};
const handleTouchMove = (e) => {
setIsDragging(true);
};
const handleTouchStop = () => {
if (!isDragging) {
// 没在拖动
}
settimeout(() => {
setIsDragging(false)
}, 0)
}
return (
<Draggable
onStart={handleTouchStart}
onDrag={handleTouchMove}
onStop={handleTouchStop}
>
<div style={{ width: '100px', height: '100px', backgroundColor: 'lightblue' }}>
Drag me
</div>
</Draggable>
);
};
export default DraggableComponent;
// 下方是判断移动位置
import React, { useState } from 'react';
import Draggable from 'react-draggable';
const DraggableComponent = () => {
const [isDragging, setIsDragging] = useState(false);
const [startX, setStartX] = useState(null);
const [startY, setStartY] = useState(null);
const handleTouchStart = (e) => {
setStartX(e.touches[0].clientX);
setStartY(e.touches[0].clientY);
setIsDragging(false);
};
const handleTouchMove = (e) => {
const moveX = e.touches[0].clientX;
const moveY = e.touches[0].clientY;
if (Math.abs(moveX - startX) > 5 || Math.abs(moveY - startY) > 5) {
setIsDragging(true);
}
};
const handleTouchStop = () => {
setIsDragging(false)
}
return (
<Draggable
onStart={handleTouchStart}
onDrag={handleTouchMove}
onStop={handleTouchStop}
>
<div style={{ width: '100px', height: '100px', backgroundColor: 'lightblue' }}>
Drag me
</div>
</Draggable>
);
};
export default DraggableComponent;
拖动范围不超过浏览器窗口
// 拖动范围不超过浏览器窗口
<Draggable
bounds="body"
>
<div style={{ width: '100px', height: '100px', backgroundColor: 'lightblue' }}>
Drag me
</div>
</Draggable>
拖动范围不超过某个div盒子内部
import Draggable from 'react-draggable';
const App = () => {
const boundsRef = useRef(null);
return (
<div ref={boundsRef} style={{ width: '400px', height: '400px', border: '1px solid black', position: 'relative' }}>
<Draggable bounds={boundsRef}>
<div className="draggable-box" style={{ width: '100px', height: '100px', background: 'red' }}>
Drag Me
</div>
</Draggable>
</div>
);
};
export default App;
使用react-draggable包裹react-select组件时,点击react-select显示的下拉框位置不在下方,位置错乱了如何解决
import React from 'react';
import Draggable from 'react-draggable';
import Select from 'react-select';
const customStyles = {
menuPortal: base => ({ ...base, zIndex: 9999 }), // 设置z-index确保下拉框在最上层显示
};
const App = () => {
return (
<Draggable>
<Select
options={options}
styles={customStyles}
menuPortalTarget={document.body}
/>
</Draggable>
);
};
```
通过设置menuPortalTarget为document.body,可以将下拉框渲染到body节点中,确保其显示在正确的位置。同时,通过自定义样式customStyles,可以设置下拉框的z-index等样式属性。
更多推荐
所有评论(0)