一、鼠标行为坐标系
事件对象属性 | 解释 |
---|---|
e.clientX/Y | 鼠标相对于当前可视区域的坐标(不包括滚动条的距离) |
e.x/y | 同clientX/Y相同(老版FF不支持) |
e.pageX/Y(常用) | 鼠标位置相对于当前文档的坐标(包含滚动条的距离,IE9以下不支持) |
e.layerX/Y | 同pageX/Y相同(IE11以下同clientX/Y) |
e.screenX/Y | 鼠标位置相对于屏幕的坐标(包含工具栏,浏览器以外的距离) |
e.offsetX/Y | 鼠标位置相对于块元素的坐标(包含边框,Safari不包括边框) |
二、pageXY兼容封装
function pagePos(e) {
var sLeft = getScrollOffset().left, // 获取滚动距离
sTop = getScrollOffset().top,
cLeft = document.documentElement.clientLeft || 0, // 获取文档偏移,IE8及一下不支持
cTop = document.documentElement.clientTop || 0;
return {
X: e.clientX + sLeft - cLeft,
Y: e.clientY + sTop - cTop
}
}
三、拖拽函数封装
(1)鼠标按下后移动
- mousedown:鼠标按下
- mouseup:鼠标抬起
- mousemove:鼠标移动
鼠标按下并移动: mousemove写在mousedown里面
(2)简易版
document.onmousemove = function (e) {
var e = e || window.event,
page = pagePos(e);
box.style.left = page.X + 'px';
box.style.top = page.Y + 'px';
}
缺点:
- 移动的时候是获取鼠标xy距离然后给这个盒子
- 拖动的是左上角
(3)正式版
box.onmousedown = function (e) {
var e = e || window.event,
page = pagePos(e),
x = pagePos(e).X - getStyles(box, 'left'),
y = pagePos(e).Y - getStyles(box, 'top')
// x = e.offsetX,
// y = e.offsetY;
// 这里为什么给document移动而不是box?
// 因为当瞬间移动鼠标的时候,获取鼠标的xy的时候和给box的topleft赋值的时候的帧率不相符了,就会赋值不过来
// 所以但鼠标脱离盒子范围的时候就会停止移动
// 用document可以增加鼠标移动的范围从而避免这种情况
document.onmousemove = function (e) {
var e = e || window.event,
page = pagePos(e);
box.style.left = (page.X - x) + 'px';
box.style.top = (page.Y - y) + 'px';
}
// 为什么这里用document而不用box? 和上面同理
document.onmouseup = function (e) {
this.onmousemove = null;
this.onmouseup = null;
}
}
(4)拖拽函数封装
function elemDrag(elem) {
addEvent(elem, 'mousedown', function (e) {
var e = e || window.event;
x = pagePos(e).X - getStyles(elem, 'left');
y = pagePos(e).Y - getStyles(elem, 'top');
addEvent(document, 'mousemove', mouseMove);
addEvent(document, 'mouseup', mouseUp);
cancleBubble(e); // 取消冒泡行为
preventDefaultEvent(e); // 阻止默认行为
})
function mouseMove(e) {
var e = e || window.event;
elem.style.top = pagePos(e).Y - y + 'px';
elem.style.left = pagePos(e).X - x + 'px';
}
function mouseUp(e) {
var e = e || window.event;
removeEvent(document, 'mousemove', mouseMove);
removeEvent(document, 'mouseup', mouseUp);
}
}
四、作业
(1)可拖动的模态框
要求:
- 拖动
- 关闭
- 边界限制
- 可拖动区域
- 用插件的方式写(面向对象思想)