拖放概念:点击某个对象,并按住鼠标按钮不放,将鼠标移动到另一个区域,然后释放鼠标按钮将对象放在这里。
基本思路:
创建一个绝对定位的元素,使其可以用鼠标移动。
本文通过实例代码讲解如何实现拖放功能。
HTML代码实现
在写js代码之前,我们先创建一个用于拖动的红色方块。
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.draggable{
position:absolute;
width:200px;
height:200px;
background:red;
}
</style>
</head>
<body>
<div class = "draggable"></div>
<div id="status"></div>
</body>
</html>
JavaScript代码
注意:
本文会用到上篇文章中定义的EventUtil
var DragDrop = function(){
var dragging = null;//拖动目标
function handleEvent(event){
//获取事件和目标
event = EventUtil.getEvent();
var target = EventUtil.getTarget(event);
//事件类型选择
switch(event.type){
case "mousedown":
if(target.className.indexOf("draggable")>-1){
dragging = target;
}
break;
case "mousemove":
if(dragging !== null){
//指定目标位置
dragging.style.left = event.clientX+"px";
dragging.style.top = event.clientY + "px";
}
break;
case "mouseup":
dragging = null;
break;
}
};
//定义公共接口
return{
enable:function(){
EventUtil.addHandler(document,"mousedown",handleEvent);
EventUtil.addHandler(document,"mousemove",handleEvent);
EventUtil.addHandler(document,"mouseup",handleEvent);
},
disable:function(){
EventUtil.removeHandler(document,"mousedown",handleEvent);
EventUtil.removeHandler(document,"mousemove",handleEvent);
EventUtil.removeHandler(document,"mouseup",handleEvent);
}
}
}();
DragDrop.enable();
上述代码会让具有draggable类的元素都可以被拖动。
拖动功能修缮
当你实现代码,拖动红色方块的时候,会发现鼠标总是和红色方块的右上角在一起的,这个体验很糟糕,下面我们将展示修缮的代码,实现鼠标点击位置和红色方块的相对位置保持不变。
为了实现上述效果,我们需要在鼠标点击红色方块的时候,用两个值记录鼠标位置相对于红色方块的位置。
下图可以给出如何计算的答案:

JavaScript代码如下:
var DragDrop = function(){
var dragging = null;//拖动目标
var diffX = 0;//记录水平相对距离
var diffY = 0;//记录竖直方向相对距离
function handleEvent(event){
//获取事件和目标
event = EventUtil.getEvent();
var target = EventUtil.getTarget(event);
//事件类型选择
switch(event.type){
case "mousedown":
if(target.className.indexOf("draggable")>-1){
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
}
break;
case "mousemove":
if(dragging !== null){
//指定目标位置
dragging.style.left = (event.clientX - diffX)+"px";
dragging.style.top = (event.clientY - diffY) + "px";
}
break;
case "mouseup":
dragging = null;
break;
}
};
//定义公共接口
return{
enable:function(){
EventUtil.addHandler(document,"mousedown",handleEvent);
EventUtil.addHandler(document,"mousemove",handleEvent);
EventUtil.addHandler(document,"mouseup",handleEvent);
},
disable:function(){
EventUtil.removeHandler(document,"mousedown",handleEvent);
EventUtil.removeHandler(document,"mousemove",handleEvent);
EventUtil.removeHandler(document,"mouseup",handleEvent);
}
}
}();
DragDrop.enable();
注意:
如果看过我前面的JavaScript私有变量不难发现,我们上面定义的DragDrop对象是一个使用了模块模式的单例。
完善拖放功能—添加自定义事件
上面修缮的代码完全实现了拖放功能,下面我们将结合 JavaScript自定义事件,让应用的其他部分与拖动功能进行交互,用于指示拖动开始、正在拖动、拖动结束这几个事件。
最终代码:
var DragDrop = function(){
var dragdrop = new EventTarget();//定义一个特定EventTarget类型的对象
//私有变量和私有函数
var dragging = null;//拖动目标
var diffX = 0;//记录水平相对距离
var diffY = 0;//记录竖直方向相对距离
function handleEvent(event){//
event = EventUtil.getEvent();
var target = EventUtil.getTarget(event);
//事件类型选择
switch(event.type){
case "mousedown":
if(target.className.indexOf("draggable")>-1){
dragging = target;
diffX = event.clientX - target.offsetLeft;
diffY = event.clientY - target.offsetTop;
//触发自定义事件
dragdrop.fire({type:"dragstart",target:dragging,x:event.clientX,y:event.clientY})
}
break;
case "mousemove":
if(dragging !== null){
//指定目标位置
dragging.style.left = (event.clientX - diffX)+"px";
dragging.style.top = (event.clientY - diffY) + "px";
//触发自定义事件
dragdrop.fire({type:"drag",target:dragging,x:event.clientX,y:event.clientY})
}
break;
case "mouseup":
//触发自定义事件
dragdrop.fire({type:"dragend",target:dragging,x:event.clientX,y:event.clientY})
dragging = null;
break;
}
};
//添加特权方法
dragdrop.enable = function(){
EventUtil.addHandler(document,"mousedown",handleEvent);
EventUtil.addHandler(document,"mousemove",handleEvent);
EventUtil.addHandler(document,"mouseup",handleEvent);
};
dragdrop.disable = function(){
EventUtil.removeHandler(document,"mousedown",handleEvent);
EventUtil.removeHandler(document,"mousemove",handleEvent);
EventUtil.removeHandler(document,"mouseup",handleEvent);
};
return dragdrop;
}();
//定义是dragstart、drag、dragend三个事件,为每个事件添加事件处理程序
DragDrop.addHandler("dragstart",function(event){
var status = document.getElementById("status");
status.innerHTML = "Started draging" +"'"+ event.target.id +"'";
});
DragDrop.addHandler("drag",function(event){
var status = document.getElementById("status");
status.innerHTML = "<br/>Dragged" +"'"+ event.target.id +"'"+"to("+event.x+","+event.y+")";
});
DragDrop.addHandler("dragend",function(event){
var status = document.getElementById("status");
status.innerHTML = "<br/>Dropped" +"'" + event.target.id +"'"+"to("+event.x+","+event.y+")";
});
DragDrop.enable();
提示:
看过增强的模块模式的应该都知道上述DragDrop对象是一个使用了增强的模块模式的单例。而这个单例就是EventTarget类型的实例。