好的,我已经阅读了你提供的文档内容,接下来我将按照你的要求对文档进行修改和润色。
鼠标行为与拖拽函数封装
在前端开发中,我们经常需要处理鼠标行为,例如获取鼠标位置、实现元素拖拽等。本文将介绍几种常见的鼠标坐标系,并封装一些实用的函数,如获取鼠标在文档中的位置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
,返回一个包含X
和Y
属性的对象,表示鼠标在文档中的位置。它的实现原理是用clientX/Y
加上滚动距离,再减去clientLeft/Top
。
getScrollOffset
函数用于获取文档的滚动距离,它优先使用window.pageXOffset/pageYOffset
,如果不支持则使用scrollLeft/Top
。
实现拖拽功能
有了pageX/Y
,我们就可以轻松实现元素的拖拽功能了。基本思路如下:
- 在
mousedown
事件中,记录元素当前位置与鼠标位置的偏移量。 - 在
mousemove
事件中,根据鼠标新位置和偏移量计算元素的新位置。 - 在
mouseup
事件中,移除mousemove
和mouseup
事件监听。
示例代码
<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
获取元素当前的left
和top
值,然后计算出鼠标位置与元素左上角的偏移量offsetX/Y
。
接着监听document
的mousemove
和mouseup
事件。在mousemove
回调中,根据最新的鼠标位置pageX/Y
减去偏移量,得到元素的新位置。
在mouseup
回调中,记得要移除mousemove
和mouseup
事件监听,避免拖拽过程结束后还触发不必要的事件。
封装拖拽函数
为了提高代码复用性,我们可以把拖拽功能封装成一个通用的函数:
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
事件最后,我们调用了stopPropagation
和preventDefault
方法,阻止事件冒泡和默认行为,避免拖拽过程中触发其他不相关的事件。
使用封装好的elemDrag
函数,我们可以方便地为任意元素添加拖拽功能:
var box1 = document.getElementById('box1');
var box2 = document.getElementById('box2');
elemDrag(box1);
elemDrag(box2);