js拖拽一些常见的思路方法整理


Posted in Javascript onMarch 19, 2014

js拖拽的常见思路

1.通过onmousedown,onmousemove,onmouseup分别模拟开始拖拽,拖拽中和拖拽结束时的事件()。

如果手机的触摸事件的话则分别是ontouchstart,ontouchmove和ontouchend。

2.鼠标按下即发生onmousedown事件时:获取鼠标位置,获取被拖动元素的位置,记录两者之间的纵横坐标的差值()。对document元素绑定onmousemove,onmouseup事件。

刚开始接触js拖拽时,我当时疑惑的是为什么是对document绑定而不是对被拖动的元素绑定呢?原来是如果对被拖动元素绑定的话当鼠标拖动过快时,会导致鼠标与被拖动元素的脱离。

3.鼠标拖动即发生onmousemove事件时:将被拖拽元素的position改成绝对位置,这个可以通过left和top改变该元素的位置,从而使得该元素随着鼠标的拖拽而移动。获取鼠标位置,将鼠标x坐标(e.clientX)减去第2步储存的横坐标差作为被拖动元素的left值,将鼠标x坐标(e.clientY)减去第2步储存的纵坐标差作为被拖动元素的top值。实现元素跟随鼠标拖动的效果。

4.鼠标按键弹起即发生onmouseup事件时:清空onmousemove和onmouseup事件

比较流行的拖拽插件dom-drag类库(作者: Aaron Boodman)

其源代码如下

/*其中( dom-drag.js )文件************************************************** 
* dom-drag.js 
* 09.25.2001 
* www.youngpup.net 
************************************************** 
* 10.28.2001 - fixed minor bug where events 
* sometimes fired off the handle, not the root. 
**************************************************/ var Drag = { 
obj : null, 
init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) 
{ 
o.onmousedown = Drag.start; 
o.hmode = bSwapHorzRef ? false : true ; 
o.vmode = bSwapVertRef ? false : true ; 
o.root = oRoot && oRoot != null ? oRoot : o ; 
if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px"; 
if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px"; 
if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px"; 
if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px"; 
o.minX = typeof minX != 'undefined' ? minX : null; 
o.minY = typeof minY != 'undefined' ? minY : null; 
o.maxX = typeof maxX != 'undefined' ? maxX : null; 
o.maxY = typeof maxY != 'undefined' ? maxY : null; 
o.xMapper = fXMapper ? fXMapper : null; 
o.yMapper = fYMapper ? fYMapper : null; 
o.root.onDragStart = new Function(); 
o.root.onDragEnd = new Function(); 
o.root.onDrag = new Function(); 
}, 
start : function(e) 
{ 
var o = Drag.obj = this; 
e = Drag.fixE(e); 
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); 
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); 
o.root.onDragStart(x, y); 
o.lastMouseX = e.clientX; 
o.lastMouseY = e.clientY; 
if (o.hmode) { 
if (o.minX != null) o.minMouseX = e.clientX - x + o.minX; 
if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX; 
} else { 
if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x; 
if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x; 
} 
if (o.vmode) { 
if (o.minY != null) o.minMouseY = e.clientY - y + o.minY; 
if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY; 
} else { 
if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y; 
if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y; 
} 
document.onmousemove = Drag.drag; 
document.onmouseup = Drag.end; 
return false; 
}, 
drag : function(e) 
{ 
e = Drag.fixE(e); 
var o = Drag.obj; 
var ey = e.clientY; 
var ex = e.clientX; 
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom); 
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right ); 
var nx, ny; 
if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX); 
if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX); 
if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY); 
if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY); 
nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1)); 
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1)); 
if (o.xMapper) nx = o.xMapper(y) 
else if (o.yMapper) ny = o.yMapper(x) 
Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px"; 
Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px"; 
Drag.obj.lastMouseX = ex; 
Drag.obj.lastMouseY = ey; 
Drag.obj.root.onDrag(nx, ny); 
return false; 
}, 
end : function() 
{ 
document.onmousemove = null; 
document.onmouseup = null; 
Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]), 
parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"])); 
Drag.obj = null; 
}, 
fixE : function(e) 
{ 
if (typeof e == 'undefined') e = window.event; 
if (typeof e.layerX == 'undefined') e.layerX = e.offsetX; 
if (typeof e.layerY == 'undefined') e.layerY = e.offsetY; 
return e; 
} 
};

二:拖拽排序也是一种常见的效果

常见实现思路

1.将点击进行拖拽的元素转换为绝对路径,同时新建一个临时元素替代其所在的位置。

2.移动过程中通过循环计算鼠标与剩余元素的位置关系,如果鼠标位置处于该元素中时,在该元素的nextSibling前面插入第1步时创建的临时元素;

3.结束时在临时元素前面插入被拖拽元素,删除临时元素。

网上有个冷月无声博主写的挺好的,在此转载一下其代码

以下为其代码

(function(win, doc){ 
var _this = null; 
var info = {}; 
var list = []; 
var Sortable = function(opts) { 
this.opts = opts; 
_this = this; 
list = X.getByClass(this.opts.sortClass, doc); 
X.addEvent(doc, 'mousedown', this.handleEvent); 
X.addEvent(doc, 'mousemove', this.handleEvent); 
X.addEvent(doc, 'mouseup', this.handleEvent); 
}; 
Sortable.prototype = { 
handleEvent: function(event) { 
var e = event || win.event; 
var target = event.target || event.srcElement; 
switch (event.type) { 
case 'mousedown': 
X.hasClass(target, _this.opts.sortClass) && _this.downEvent.call(_this, e, target); 
break; 
case 'mousemove': 
info.dObj && _this.moveEvent.call(_this, e, target); 
break; 
case 'mouseup': 
info.dObj && _this.upEvent.call(_this, e, target); 
break; 
default: break; 
} 
}, 
downEvent: function(e, target) { 
info.dObj = target; 
var off = X.getOffset(target); 
target.x = e.clientX - off[0]; 
target.y = e.clientY - off[1]; 
target.style.position = 'absolute'; 
target.style.left = off[0] +'px'; 
target.style.top = off[1] +'px'; info.vObj = doc.createElement('div'); 
info.vObj.style.width = off[2] +'px'; 
info.vObj.style.height = off[3] +'px'; 
target.parentNode.insertBefore(info.vObj, target); 
}, 
moveEvent: function(e, target) { 
win.getSelection ? win.getSelection().removeAllRanges() : doc.selection.empty(); 
info.dObj.style.left = e.clientX - info.dObj.x +'px'; 
info.dObj.style.top = e.clientY - info.dObj.y +'px'; 
for(var i = 0; i < list.length; i++) { 
if(list[i] === info.dObj) { 
continue; 
} 
var off = X.getOffset(list[i]); 
if(e.clientX > off[0] && e.clientX < off[0] + off[2] && e.clientY > off[1] && e.clientY < off[1] + off[3]) { 
switch (true) { 
case e.clientY < (off[1] + off[3]) / 2: 
list[i].parentNode.insertBefore(info.vObj, list[i]); 
break; 
case !list[i].nextSibling: 
list[i].parentNode.appendChild(info.vObj); 
break; 
default: 
list[i].parentNode.insertBefore(info.vObj, list[i].nextSibling); 
break; 
} 
} 
} 
}, 
upEvent: function(e, target) { 
info.dObj.style.position = 'static'; 
info.vObj.parentNode.insertBefore(info.dObj, info.vObj); 
info.dObj.parentNode.removeChild(info.vObj); 
info = {}; 
} 
}; 
win.Sortable = Sortable; 
})(window, document);
Javascript 相关文章推荐
JQuery 弹出框定位实现方法
Dec 02 Javascript
从零开始学习jQuery (四) jQuery中操作元素的属性与样式
Feb 23 Javascript
js/jquery获取浏览器窗口可视区域高度和宽度以及滚动条高度实现代码
Dec 17 Javascript
使用Grunt.js管理你项目的应用说明
Apr 24 Javascript
深入理解JavaScript系列(47):对象创建模式(上篇)
Mar 04 Javascript
jquery表单验证插件(jquery.validate.js)的3种使用方式
Mar 28 Javascript
JQuery包裹DOM节点的方法
Jun 11 Javascript
jQuery超酷平面式时钟效果代码分享
Mar 30 Javascript
Bootstrap Metronic完全响应式管理模板之菜单栏学习笔记
Jul 08 Javascript
jquery 多个radio的click事件实例
Dec 03 Javascript
获取当前按钮或者html的ID名称实例(推荐)
Jun 23 Javascript
在angularJs中进行数据遍历的2种方法
Oct 08 Javascript
使用jquery实现以post打开新窗口
Mar 19 #Javascript
jquery判断小数点两位和自动删除小数两位后的数字
Mar 19 #Javascript
改变隐藏的input中value值的方法
Mar 19 #Javascript
js获取url中的参数且参数为中文时通过js解码
Mar 19 #Javascript
JS 打印界面的CSS居中代码适用所有浏览器
Mar 19 #Javascript
兼容所有浏览器的js复制插件Zero使用介绍
Mar 19 #Javascript
javascript + jquery实现定时修改文章标题
Mar 19 #Javascript
You might like
用PHP制作静态网站的模板框架(四)
2006/10/09 PHP
使用PHP导出Redis数据到另一个Redis中的代码
2014/03/12 PHP
php使用GD实现颜色渐变实例
2015/06/02 PHP
ThinkPHP函数详解之M方法和R方法
2015/09/10 PHP
PHP读取zip文件的方法示例
2016/11/17 PHP
location.href语句与火狐不兼容的问题
2010/07/04 Javascript
JQuery1.4+ Ajax IE8 内存泄漏问题
2010/10/15 Javascript
js中 关于undefined和null的区别介绍
2013/04/16 Javascript
JavaScript字符串插入、删除、替换函数使用示例
2013/07/25 Javascript
jquery实现多行文字图片滚动效果示例代码
2014/10/10 Javascript
js数组的基本操作(很全自己整理的)
2014/10/16 Javascript
js实现按钮控制图片360度翻转特效的方法
2015/02/17 Javascript
jQuery与getJson结合的用法实例
2015/08/07 Javascript
Nodejs express框架一个工程中同时使用ejs模版和jade模版
2015/12/28 NodeJs
Ionic2开发环境搭建教程
2020/08/20 Javascript
vue嵌套路由与404重定向实现方法分析
2018/05/04 Javascript
vue中动态添加class类名的方法
2018/09/05 Javascript
基于Vue.js+Nuxt开发自定义弹出层组件
2020/10/09 Javascript
Django中URL视图函数的一些高级概念介绍
2015/07/20 Python
Python中%r和%s的详解及区别
2017/03/16 Python
python顺序的读取文件夹下名称有序的文件方法
2018/07/11 Python
利用python实现简易版的贪吃蛇游戏(面向python小白)
2018/12/30 Python
对Python捕获控制台输出流的方法详解
2019/01/07 Python
浅谈python的深浅拷贝以及fromkeys的用法
2019/03/08 Python
pycharm 安装JPype的教程
2019/08/08 Python
Python求平面内点到直线距离的实现
2020/01/19 Python
html5小程序飞入购物车(抛物线绘制运动轨迹点)
2020/10/19 HTML / CSS
新员工入职感言
2014/02/01 职场文书
《莫泊桑拜师》教学反思
2014/04/23 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
先进事迹材料怎么写
2014/12/30 职场文书
公务员年度个人总结
2015/02/12 职场文书
七一慰问简报
2015/07/20 职场文书
感恩教师节主题班会
2015/08/12 职场文书
使用 Apache 反向代理的设置技巧
2022/01/18 Servers
Python数据处理的三个实用技巧分享
2022/04/01 Python