跳到主要内容

好的,我已经阅读了你提供的文档内容,接下来我将按照你的要求对文档进行修改和润色。

鼠标行为与拖拽函数封装

在前端开发中,我们经常需要处理鼠标行为,例如获取鼠标位置、实现元素拖拽等。本文将介绍几种常见的鼠标坐标系,并封装一些实用的函数,如获取鼠标在文档中的位置pageX/Y以及通用的元素拖拽函数。

鼠标坐标系

在处理鼠标事件时,我们可以通过事件对象e获取鼠标的位置信息。常见的鼠标坐标系有以下几种:

e.clientX/Y:鼠标位置相对于当前可视区域的坐标,不包括滚动条的距离。

e.pageX/Y:鼠标位置相对于当前文档的坐标,包含滚动条的距离。IE9以下不支持。

e.screenX/Y:鼠标位置相对于当前屏幕的坐标。

e.x/y:与clientX/Y相同,但火狐浏览器不支持e.y

e.layerX/Y:与pageX/Y相同,但IE11以下与clientX/Y相同。

e.offsetX/Y:鼠标位置相对于当前块元素的坐标,包含边框。但Safari不包含边框。

封装 pageX/Y

由于pageX/Y在低版本 IE 中不支持,我们可以封装一个兼容性的函数来获取:

function pagePos(e) {
var scrollLeft = getScrollOffset().left;
var scrollTop = getScrollOffset().top;
var clientLeft = document.documentElement.clientLeft || 0;
var clientTop = document.documentElement.clientTop || 0;

return {
X: e.clientX + scrollLeft - clientLeft,
Y: e.clientY + scrollTop - clientTop,
};
}

function getScrollOffset() {
if (window.pageXOffset) {
return {
left: window.pageXOffset,
top: window.pageYOffset,
};
} else {
return {
left: document.body.scrollLeft + document.documentElement.scrollLeft,
top: document.body.scrollTop + document.documentElement.scrollTop,
};
}
}

上面的pagePos函数接收一个事件对象e,返回一个包含XY属性的对象,表示鼠标在文档中的位置。它的实现原理是用clientX/Y加上滚动距离,再减去clientLeft/Top

getScrollOffset函数用于获取文档的滚动距离,它优先使用window.pageXOffset/pageYOffset,如果不支持则使用scrollLeft/Top

实现拖拽功能

有了pageX/Y,我们就可以轻松实现元素的拖拽功能了。基本思路如下:

  1. mousedown事件中,记录元素当前位置与鼠标位置的偏移量。
  2. mousemove事件中,根据鼠标新位置和偏移量计算元素的新位置。
  3. mouseup事件中,移除mousemovemouseup事件监听。

示例代码

<div class="box"></div>
<script>
var box = document.querySelector('.box');
var offsetX, offsetY;

box.addEventListener('mousedown', function (e) {
var boxLeft = parseInt(getComputedStyle(box).left);
var boxTop = parseInt(getComputedStyle(box).top);
offsetX = pagePos(e).X - boxLeft;
offsetY = pagePos(e).Y - boxTop;

document.addEventListener('mousemove', mouseMove);
document.addEventListener('mouseup', mouseUp);
});

function mouseMove(e) {
var pageX = pagePos(e).X;
var pageY = pagePos(e).Y;
box.style.left = pageX - offsetX + 'px';
box.style.top = pageY - offsetY + 'px';
}

function mouseUp() {
document.removeEventListener('mousemove', mouseMove);
document.removeEventListener('mouseup', mouseUp);
}
</script>

mousedown事件处理函数中,我们先用getComputedStyle获取元素当前的lefttop值,然后计算出鼠标位置与元素左上角的偏移量offsetX/Y

接着监听documentmousemovemouseup事件。在mousemove回调中,根据最新的鼠标位置pageX/Y减去偏移量,得到元素的新位置。

mouseup回调中,记得要移除mousemovemouseup事件监听,避免拖拽过程结束后还触发不必要的事件。

封装拖拽函数

为了提高代码复用性,我们可以把拖拽功能封装成一个通用的函数:

function elemDrag(elem) {
var offsetX, offsetY;

elem.addEventListener('mousedown', function (e) {
var elemLeft = parseInt(getComputedStyle(elem).left);
var elemTop = parseInt(getComputedStyle(elem).top);
offsetX = pagePos(e).X - elemLeft;
offsetY = pagePos(e).Y - elemTop;

document.addEventListener('mousemove', mouseMove);
document.addEventListener('mouseup', mouseUp);

e.stopPropagation();
e.preventDefault();
});

function mouseMove(e) {
var pageX = pagePos(e).X;
var pageY = pagePos(e).Y;
elem.style.left = pageX - offsetX + 'px';
elem.style.top = pageY - offsetY + 'px';
}

function mouseUp() {
document.removeEventListener('mousemove', mouseMove);
document.removeEventListener('mouseup', mouseUp);
}
}

elemDrag函数接收一个 DOM 元素作为参数,为该元素添加拖拽功能。它的实现与前面的示例代码类似,只是使用了更语义化的变量名。

此外,在mousedown事件最后,我们调用了stopPropagationpreventDefault方法,阻止事件冒泡和默认行为,避免拖拽过程中触发其他不相关的事件。

使用封装好的elemDrag函数,我们可以方便地为任意元素添加拖拽功能:

var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
elemDrag(box1);
elemDrag(box2);