元素拖动

拖动元素首先我们得明确整个拖动事件中相关的元素,我总结有3个相关元素:

  • 拖动的元素: 目标元素
  • 触发拖动事件的元素:绑定mousedown事件的元素,它可能就是目标元素
  • 响应目标元素的元素:绑定mousemove事件的元素,它是为了响应拖动元素的移动的,后面统称父元素

获取鼠标初始位置

function getScrollOffset(w) {
    w = w || window;

    if (w.pageXOffset != null) return { x: w.pageXOffset, y: w.pageYOffset };
    var d =w.document;
    if (document.compatMode === "CSS1Compat")
        return { x: d.documentElement.scrollLeft, y:d.documentElement.scrollTop };

    return { x: d.body.scrollLeft, y: d.body.scrollTop };
}
const scroll = getScrollOffset();
const startX = e.clientX + scroll.x;
const startY = e.clientY + scroll.y;
复制代码

注意: clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标,所以我们必须考虑页面滚动的情况。

获取目标元素到父元素的距离

function getTargetLeft(element, parent = null) {
    let offsetLeft = element.offsetLeft;
    let current = element.offsetParent;
    
    while (current !== parent) {
        offsetLeft += current.offsetLeft;
        current = current.offsetParent
    }
	return offsetLeft;	   
}

function getTargetTop(element, parent = null) {
    let offsetTop = element.offsetTop;
    let current = element.offsetParent;
    
    while (current !== parent) {
        offsetTop += current.offsetTop;
        current = current.offsetParent
    }
	return offsetTop;	   
}

const origX = getTargetLeft(e.target);
const origY = getTargetTop(e.target);
复制代码

获取鼠标相对mousedown事件元素的距离

const deltaX = startX - origX;
const deltaY = startY - origY;
复制代码

整合后完整代码

html
<!DOCTYPE html>
<html lang="cn">
<head>
	<meta charset="UTF-8">
  	<title>Title</title>
</head>
<body>
    <div id="droptarget" style="width: 100px; height: 100px; background: red; position: absolute;">
       <div onmousedown="drag(this.parentNode, event)">title</div>
       <p>测试测试</p>
    </div>
</body>
复制代码

drag.js

function getScrollOffset(w) {
	w = w || window;

	if (w.pageXOffset != null) return { x: w.pageXOffset, y: w.pageYOffset };

	var d =w.document;
	if (document.compatMode === "CSS1Compat")
		return { x: d.documentElement.scrollLeft, y:d.documentElement.scrollTop };

	return { x: d.body.scrollLeft, y: d.body.scrollTop };
}

function drag(targetElement, e) {
    const scroll = getScrollOffset();
    const startX = e.clientX + scroll.x;
    const startY = e.clientY + scroll.y;
    function getTargetLeft(element, parent = null) {
        let offsetLeft = element.offsetLeft;
        let current = element.offsetParent;

        while (current !== parent) {
            offsetLeft += current.offsetLeft;
            current = current.offsetParent
        }
        return offsetLeft;	   
	}

    function getTargetTop(element, parent = null) {
        let offsetTop = element.offsetTop;
        let current = element.offsetParent;

        while (current !== parent) {
            offsetTop += current.offsetTop;
            current = current.offsetParent
        }
        return offsetTop;	   
    }
    const origX = getTargetLeft(e.target);
    const origY = getTargetTop(e.target);
    const deltaX = startX - origX;
    const deltaY = startY - origY;
    
    document.addEventListener("mousemove", moveHandler, true);
    document.addEventListener("mouseup", upHandler, true);
    
    function moveHandler(e) {
    	const scroll = getScrollOffset();

    	targetElement.style.left = (e.clientX + scroll.x - deltaX) + "px";
    	targetElement.style.top = (e.clientY + scroll.y - deltaY) + "px";
        e.stopPropagation();
    }

    function upHandler(e) {
        document.removeEventListener("mouseup", upHandler, true);
        document.removeEventListener("mousemove", moveHandler, true);
        e.stopPropagation();
    }
}
复制代码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值