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 相关文章推荐
js整数字符串转换为金额类型数据(示例代码)
Dec 26 Javascript
jquery缓动swing liner控制动画过程不同时刻的速度
May 29 Javascript
JavaScript中document对象使用详解
Jan 06 Javascript
详谈javascript中的cookie
Jun 03 Javascript
c#程序员对TypeScript的认识过程
Jun 19 Javascript
javascript实现超炫的向上滑行菜单实例
Aug 03 Javascript
每天一篇javascript学习小结(Array数组)
Nov 11 Javascript
url中的特殊符号有什么含义(推荐)
Jun 17 Javascript
javascript中的面向对象
Mar 30 Javascript
使用javaScript实现鼠标拖拽事件
Apr 03 Javascript
Flutter 超实用简单菜单弹出框 PopupMenuButton功能
Aug 06 Javascript
Vue实现购物车详情页面的方法
Aug 20 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用身份证号获取星座和生肖的方法
2013/11/07 PHP
PHP用反撇号执行外部命令
2015/04/14 PHP
PHP 访问数据库配置通用方法(json)
2018/05/20 PHP
JQuery this 和 $(this) 的区别
2009/08/23 Javascript
jquery ready函数源代码研究
2009/12/06 Javascript
关于JavaScript定义类和对象的几种方式
2010/11/09 Javascript
js定时器怎么写?就是在特定时间执行某段程序
2013/10/11 Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
2013/11/14 Javascript
使用JS取得焦点(focus)元素代码
2014/03/22 Javascript
基于javascript的COOkie的操作实现只能点一次
2014/12/26 Javascript
js实现文本框选中的方法
2015/05/26 Javascript
TypeScript 学习笔记之基本类型
2015/06/19 Javascript
Bootstrap教程JS插件弹出框学习笔记分享
2016/05/17 Javascript
浅谈javascript运算符——条件,逗号,赋值,()和void运算符
2016/07/15 Javascript
使用jQuery实现两个div中按钮互换位置的实例代码
2017/09/21 jQuery
JS简单实现点击跳转登陆邮箱功能的方法
2017/10/31 Javascript
微信小程序实现给嵌套template模板传递数据的方式总结
2017/12/18 Javascript
深入浅析Vue全局组件与局部组件的区别
2018/06/15 Javascript
layer父页获取弹出层输入框里面的值方法
2019/09/02 Javascript
jQuery实现小火箭返回顶部特效
2020/02/03 jQuery
如何基于jQuery实现五角星评分
2020/09/02 jQuery
Vue+Vant 图片上传加显示的案例
2020/11/03 Javascript
JS获取一个字符串中指定字符串第n次出现的位置
2021/02/10 Javascript
django在接受post请求时显示403forbidden实例解析
2018/01/25 Python
详解用TensorFlow实现逻辑回归算法
2018/05/02 Python
Python使用Pandas库常见操作详解
2020/01/16 Python
keras实现多种分类网络的方式
2020/06/11 Python
Jabra捷波朗美国官网:用于办公、车载和运动的无线蓝牙耳麦
2017/02/01 全球购物
巴西男士个人护理产品商店:SHOP4MEN
2017/08/07 全球购物
学雷锋活动总结范文
2014/04/25 职场文书
全运会口号
2014/06/20 职场文书
与死神共舞观后感
2015/06/15 职场文书
大学自主招生自荐信(2016精选篇)
2016/01/28 职场文书
《狼牙山五壮士》教学反思
2016/02/17 职场文书
小学语文课《掌声》教学反思
2016/03/03 职场文书
Vue CLI中模式与环境变量的深入详解
2021/05/30 Vue.js