JavaScript拖拽实现
背景
在学习开发了签名板之后,为了更加一步学习和理解事件的位置坐标这一块的知识点,自己用原生的js实现了一个可以拖拽的div框。
功能分析
首先,需要有一个可拖拽的对象,如图,一个比较简陋的拖拽框:
拖拽.png在这个框中。我们只能在标题栏部分才可以进行拖拽,拖拽分为三步骤:
1、鼠标在标题栏部分按下后可以进行拖拽
2、移动按下的鼠标,拖拽框也会跟着移动
3、鼠标松开,拖拽结束。
功能实现
通过上述的功能分析,可以将功能分为mousedown,mousemove,mouseup三个部分。下面一步一步对拖拽功能进行分解。
变量初始化
下面代码为这个功能需要声明的对象和变量等
var flag = false; // flag用来标志鼠标是否在标题栏部分按下去
var wrap = document.getElementById('wrap'); // 获取到整个拖拽框对象
var head = document.getElementById('tzHead'); // 获取到拖拽框中标题栏对象
var now = {
x:'',
y:''
}; // 当前的鼠标位置
var last = {
x:'',
y:''
}; // 鼠标按下的时候的鼠标位置
var initPosition = {
x:'',
y:''
}; // 鼠标按下时的拖拽框相对偏移的位置
事件绑定
head.addEventListener('mousedown',beginDrag,false);
head.addEventListener('mousemove',drag,false);
head.addEventListener('mouseup',endDrag,false);
方法实现
1、开始拖拽方法:
function beginDrag(e) {
flag = true;
last.x = e.pageX;
last.y = e.pageY;
initPosition = {
x: wrap.offsetLeft,
y: wrap.offsetTop
};
}
2、拖拽方法:
function drag(e) {
if (flag) {
now = {
x: e.pageX,
y: e.pageY
};
wrap.style.left = parseInt(now.x) - parseInt(last.x) + parseInt(initPosition.x) + 'px';
wrap.style.top = parseInt(now.y) - parseInt(last.y) + parseInt(initPosition.y) + 'px';
return false;
}
}
3、结束拖拽
function endDrag(e) {
flag = false;
}
问题
现在已经实现了最基本的拖拽功能。可是这时候会有一个问题,就是如果我们鼠标滑动的很快,就很容易鼠标从head区域出来,然后出来后松开鼠标,下次在head区域内不用点击就可以移动拖拽框,这样非常不友好。
优化
针对上面这种情况,在好好看了看代码后发现。下面这段代码是有问题的:
head.addEventListener('mousedown',beginDrag,false);
head.addEventListener('mousemove',drag,false);
head.addEventListener('mouseup',endDrag,false);
对于鼠标按下事件,必须要绑定在head区域。可是拖拽事件和鼠标松开事件应该针对于整个文档。于是改为
head.addEventListener('mousedown',beginDrag,false);
document.addEventListener('mousemove',drag,false);
document.addEventListener('mouseup',endDrag,false);
上述问题不存在了。
后续优化
对于代码功能而言已经完成了功能,但是代码质量需要很大程度的优化。
网友评论