前端时间开发的过程中,遇到一个鼠标拖拽dom的需求,这个需求还是十分常见的,与大家一起分享我的想法。
解决这个需求有两种思路,其中一种是通过H5原生的拖拽事件ondragstart、ondragend,另一种则是通过监听鼠标的onmousedown、onmousemove、onmouseup事件。
ondragstart、ondragend详解
1.首先确认需要被拖拽的dom,在上面加上属性draggable为true,否则ondragstart和ondragend和ondrag事件都无法生效。
<div draggable>
可拖拽元素
</div>
2.给父级元素和拖拽元素加样式,主要是为了定位postion:relative 和position:absolute
.parent {
position: relative,
width: 800px,
height: 800px
}
.dragDom {
position: absolute,
width: 30px,
height: 30px,
x: 10,
y: 10
}
3.在ondragStart事件中获取位置,拖拽元素在父级的位置,鼠标相对位置,在ondragEnd事件中获取鼠标位置,从而计算出鼠标移动后的相对位置,并给拖拽元素设置新的位置。
注意: 以下代码提供了拖拽的一种写法思路,不建议直接使用
const [startX, setStartX] = useState<number>(0); // 元素初始位置
const [startY, setStartY] = useState<number>(0); // 元素初始位置
let startMouseX = 0;
let startMouseY = 0;
<div className="parent ">
<div style={
{
position: 'absolute',
left: startX ,
top: startY,
}}
onDragStart={
(e) => {
let e = event || window.event;
startMouseX = e.clientX; //初始鼠标位置
startMouseY = e.clientY; //初始鼠标位置
}}
onDragEnd={
(e) => {
const DisX = e.clientX - startMouseX; // 鼠标相对移动距离
const DisY = e.clientY - startMouseY; // 鼠标相对移动距离
let newX = startX + DisX; // 被拖拽元素的新位置
let newY = startY + DisY; // 被拖拽元素的新位置
const DomWidth = e.target.offsetWidth; // dom的宽度
const DomHeight = e.target.offsetHeight; // dom的高度
// 边界判断
if(newX <= 0) {
newX = 0
}
// 父级的盒子宽度为800
if(newX >= (800 - DomWidth ) ) {
newX = 800 - DomWidth
}
if(newY <= 0) {
newY = 0
}
// 父级的盒子高度为800
if(newY >= (800 - DomHeight )) {
newY = 800 - DomHeight
}
setStartX(newX)
setStartX(newY)
}}>
被拖拽的组件
</div>
</div>
onmousedown、onmousemove、onmouseup详解
-
给父级元素和拖拽元素加样式,主要是为了定位postion:relative 和position:absolute
-
在onmousedown中获取鼠标的初始位置,并创建onmousemove的监听和onmouseup的监听
-
在onmousemove中,获取鼠标的位置,计算出鼠标与初始位置的位置差,并作出边界判断,赋值给元素的位置,
-
在onmouseup中取消掉onmousemove的监听
const [startX, setStartX] = useState<number>(0); // 元素初始位置
const [startY, setStartY] = useState<number>(0); // 元素初始位置
let startMouseX = 0;
let startMouseY = 0;
<div className="parent ">
<div style={
{
position: 'absolute',
left: startX ,
top: startY,
}}
onMouseDown={
(e) => {
let e = event || window.event;
const dom = e.target;
/** 被点击元素本身的宽和高 */
const domWidth = dom.offsetWidth;
const domHeight = dom.offsetHeight;
/** 被点击元素的边界值 */
const overRigth = 800 - domWidth;
const overBottom = 800 - domHeight;
const handler = (event: any) => {
const nowX = event.clientX;
const nowY = event.clientY;
const disX = nowX - startMouseX ;
const disY = nowY - startMouseY;
let targetX = initX + disX;
let targetY = initY + disY;
if (targetX <= 0) {
targetX = 0;
}
if (targetY <= 0) {
targetY = 0;
}
if (targetX >= overRigth) {
targetX = overRigth;
}
if (targetY >= overBottom) {
targetY = overBottom;
}
setStartX(targetX )
setStartY(targetY )
};
// 请将mousemove和mouseup放到document上,否则鼠标移动太快可能会脱节,也就是被拖拽的dom跟不上鼠标的速度。哈哈
document.addEventListener('mousemove', handler, false);
document.addEventListener(
'mouseup',
() => {
document.removeEventListener('mousemove', handler);
},
false,
);
}}
> 被拖拽组件 </div>
</div>