示例代码:http://ymlj11ftp.v323.net/demo/candrag/balance.html
//拖放效果接口
/**
* 跨平台的事件监听函数
* @param {Node} node 需要监听事件的DOM节点
* @param {String} eventType 需要监听的事件类型
* @param {Function} callback 事件监听回调函数
* @type Function 返回值为函数类型
* @return 返回监听回调函数的引用,用于释放监听
*/
function bindEvent(node,eventType,callback){
if(node.attachEvent){
if(eventType.indexOf('on')){eventType = 'on'+eventType;}
node.attachEvent(eventType,callback);
}else{
if(!eventType.indexOf('on'))
eventType = eventType.substring(2,eventType.length);
node.addEventListener(eventType,callback,false);
}
return callback;
}
/**
* 跨平台的事件监听卸载函数
* @param {Node} node 需要卸载监听事件的DOM节点
* @param {String} eventType 需要卸载监听的事件类型
* @param {Function} callback 卸载事件监听回调函数
*/
function removeEvent(node,eventType,callback){
if(node.detachEvent){
if(eventType.indexOf('on')){eventType = 'on'+eventType;}
node.detachEvent(eventType,callback);
}else{
if(!eventType.indexOf('on'))
eventType = eventType.substring(2,eventType.length);
node.removeEventListener(eventType,callback,false);
}
}
/**
* 兼容不同定位方式的通用拖动接口
* @param {Node} dragger 需要被拖动的元素
*/
//必须告诉系统,哪些元素是可以进行交互,而哪些是不行
function canDrag(dragger,onStart,onDrag,onComplete,droppables){
var drag = bindEvent(dragger,'onmousedown',function(e){
//兼容事件对象
e = e || event;
//兼容坐标属性
var pageX = e.clientX||e.pageX;
var pageY = e.clientY||e.pageY;
//兼容样式对象
var style = dragger.currentStyle||window.getComputedStyle(dragger,null);
//当没有设置left和top属性时,IE下默认值为auto
var offX = parseInt(style.left)||0;
var offY = parseInt(style.top)||0;
//获取鼠标相对于元素的间距
var offXL = pageX - offX;
var offYL = pageY - offY;
//为dragger增加onDrag属性,用来存储拖动事件
if(!dragger.onDrag){
//监听拖动事件
dragger.onDrag = bindEvent(document,'onmousemove',function(e){
e = e || event;
var x = e.clientX||e.pageX;
var y = e.clientY||e.pageY
//设置X坐标
dragger.style.left = x - offXL+'px';
//设置Y坐标
dragger.style.top = y - offYL+'px';
//当鼠标移动到可交互元素时,交互元素做出的反映
//无法使用onmouseover/onmouseout,因为被上层元素所挡
if(droppables)
for(var i=0;i<droppables.length;i++){
//当鼠标点与交互元素重叠时处理,
//模拟onmouseover和onmouseout事件
if(x > droppables[i].offsetLeft &&
x < droppables[i].offsetLeft+droppables[i].offsetWidth &&
y > droppables[i].offsetTop &&
y < droppables[i].offsetTop+droppables[i].offsetHeight ){
droppables[i].inside = 1;
droppables[i].onOver.call(droppables[i],dragger);
}else if(droppables[i].inside == 1){
//inside标志表示if体内的语句只会在鼠标与交互元素重叠过以后才会执行,
//而不是当onmousemove发生时,不停的执行,避免了浪费资源
droppables[i].inside = 0;
droppables[i].onOut.call(droppables[i],dragger);
}
}
//回调函数
if(onDrag)
onDrag.call(dragger,e);
});
//监听拖动结束事件
dragger.onDragEnd = bindEvent(document,'onmouseup',function(e){
//释放前读取事件对象
var x = e.clientX||e.pageX;
var y = e.clientY||e.pageY
//释放拖动监听和结束监听
removeEvent(document,'onmousemove',dragger.onDrag);
removeEvent(document,'onmouseup',dragger.onDragEnd);
try{
//删除拖动时所用的属性,兼容FF使用
delete dragger.onDrag;
delete dragger.onDragEnd;
}catch(e){
//删除拖动时所用的属性,兼容IE6使用
dragger.removeAttribute('onDrag');
dragger.removeAttribute('onDragEnd');
}
//当光标停留在在可交互元素上松开鼠标按键时,交互元素做出的反映
if(droppables)
for(var i=0;i<droppables.length;i++){
//当鼠标点与交互元素重叠时处理,
//模拟onmouseover和onmouseout事件
if(x > droppables[i].offsetLeft &&
x < droppables[i].offsetLeft+droppables[i].offsetWidth &&
y > droppables[i].offsetTop &&
y < droppables[i].offsetTop+droppables[i].offsetHeight ){
droppables[i].onDrop.call(droppables[i],dragger);
}
}
//回调函数
if(onComplete)
onComplete.call(dragger,e);
});
}
//回调函数
if(onStart)
onStart.call(dragger,e);
});
return function(){
//返回一个可以取消拖动功能的函数引用
//释放拖动监听和结束监听
removeEvent(document,'onmousemove',dragger.onDrag);
removeEvent(document,'onmouseup',dragger.onDragEnd);
try{
//删除拖动时所用的属性,兼容FF使用
delete dragger.onDrag;
delete dragger.onDragEnd;
}catch(e){
//删除拖动时所用的属性,兼容IE6使用
dragger.removeAttribute('onDrag');
dragger.removeAttribute('onDragEnd');
}
}
}