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 自动完成 AutoComplete(Ajax 查询)
Jul 07 Javascript
javascript showModalDialog,open取得父窗口的方法
Mar 10 Javascript
ajax上传时参数提交不更新等相关问题
Dec 11 Javascript
js有序数组的连接问题
Oct 01 Javascript
Jquery 实现table样式的设定
Jan 28 Javascript
你不知道的高性能JAVASCRIPT
Jan 18 Javascript
使用jquery.qrcode.min.js实现中文转化二维码
Mar 11 Javascript
jQuery实现的简单排序功能示例【冒泡排序】
Jan 13 Javascript
JS设计模式之数据访问对象模式的实例讲解
Sep 30 Javascript
mescroll.js上拉加载下拉刷新组件使用详解
Nov 13 Javascript
Vue使用localStorage存储数据的方法
May 27 Javascript
Vue实现导航栏点击当前标签变色功能
Aug 19 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 JSON 数据解析代码
2010/05/26 PHP
destoon实现调用热门关键字的方法
2014/07/15 PHP
PHP发送AT指令实例代码
2016/05/26 PHP
PHP设置Cookie的HTTPONLY属性方法
2017/02/09 PHP
游览器中javascript的执行过程(图文)
2012/05/20 Javascript
终于解决了IE8不支持数组的indexOf方法
2013/04/03 Javascript
JavaScript使用DeviceOne开发实战(一) 配置和起步
2015/12/01 Javascript
JS插件overlib用法实例详解
2015/12/26 Javascript
原生JavaScript实现Ajax的方法
2016/04/07 Javascript
浅谈jQuery 中的事件冒泡和阻止默认行为
2016/05/28 Javascript
javascript中获取元素标签中间的内容的实现方法
2016/10/08 Javascript
JavaScript创建对象的七种方式全面总结
2017/08/21 Javascript
VUE 使用中踩过的坑
2018/02/08 Javascript
jQuery实现滚动到底部时自动加载更多的方法示例
2018/02/18 jQuery
微信小程序实现长按删除图片的示例
2018/05/18 Javascript
详解webpack4多入口、多页面项目构建案例
2018/05/25 Javascript
Bootstrap table表格初始化表格数据的方法
2018/07/25 Javascript
在vue-cli中引入lodash.js并使用详解
2019/11/13 Javascript
python实现同时给多个变量赋值的方法
2015/04/30 Python
python绘制漏斗图步骤详解
2019/03/04 Python
深入学习python多线程与GIL
2019/08/26 Python
Python 读取用户指令和格式化打印实现解析
2019/09/02 Python
Python使用pymysql模块操作mysql增删改查实例分析
2019/12/19 Python
Python&amp;&amp;GDAL实现NDVI的计算方式
2020/01/09 Python
Python并发请求下限制QPS(每秒查询率)的实现代码
2020/06/05 Python
Django nginx配置实现过程详解
2020/09/10 Python
用CSS3实现无限循环的无缝滚动的示例代码
2017/11/01 HTML / CSS
初任培训自我鉴定
2013/10/07 职场文书
营销总经理岗位职责
2014/02/02 职场文书
小学教师师德演讲稿
2014/05/06 职场文书
2014年学校党建工作总结
2014/11/11 职场文书
致接力运动员加油稿
2015/07/21 职场文书
新入职员工工作总结
2015/10/15 职场文书
2019年教师节:送给所有老师的祝福语
2019/09/05 职场文书
CSS 伪元素::marker详解
2021/06/26 HTML / CSS
【海涛dota解说】海涛小满开黑4v5被破两路翻盘潮汐第一视角解说
2022/04/01 DOTA