JS拖拽原理
实现拖拽效果主要跟鼠标的三个事件有关:
onmousedown : 选择要拖拽的元素
onmousemove : 移动元素
onmouseup : 释放元素
三个事件的关系:
obj.onmousedown = function(ev){
var ev = ev||event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; obj.ommousemove = function(ev){ var ev = ev||event;
obj.style.left = ev.clientX - disX + 'px';
obj.style.top = ev.clientY - disY + 'px'; }
obj.onmouseup = function(){
obj.onmousemove = null;
} }
以上代码是实现拖拽的最基本方法,但是如果鼠标移动过快脱离obj,移动就会失去效果,所以移动事件(onmousemove)应该绑定在document上面,同时onmouseup也应该绑定在document上:
obj.onmousedown = function(ev){
var ev = ev||event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; document.ommousemove = function(ev){ var ev = ev||event;
obj.style.left = ev.clientX - disX + 'px';
obj.style.top = ev.clientY - disY + 'px'; }
document.onmouseup = function(){
obj.onmousemove = null;
} }
问题 拖拽的时候,如果有文字被选中,会产生问题
原因:当鼠标按下的时候,如果页面中有文字被选中,那么会触发浏览器默认拖拽文字的效果 ,拖拽图片也是一样,会类似复制一份出来一样,解决办法跟文字一样
解决:
标准: 阻止默认行为
非标准ie: 设置全局捕获setCapture()(跟事件的捕获不是一个概念)
全局捕获:
例如:页面有两个input,点击input1弹出1,点击input2弹出2 ,如果我们给input1设置全局捕获,让后续的所有操作截取到input1上面,那么此时无论点击input2还是点击文档的任何地方,包括点击桌面,
input1都会将这些点击事件截取到自己身上来执行自己的click事件,就是弹出1,这就是设置全局捕获的一个效果。
<script>
window.onload = function() { var aInput = document.getElementsByTagName('input'); aInput[0].setCapture(); //设置全局捕获 ,当我们给一个元素设置全局捕获以后,那么这个元素就会监听后续发生的所有事件,当有事件发生的时候,就会被当前设置了全局捕获的元素所触发 /*
ie : 有,并且有效果
ff : 有,但是没效果
chrome : 没有setCapture()
*/ aInput[0].onclick = function() {
alert(1);
} aInput[1].onclick = function() {
alert(2);
} }
</script>
</head> <body>
<input type="button" value="按钮一" />
<input type="button" value="按钮二" />
</body>
</html>
但是全局捕获也是有兼容性的,
ie : 有,并且有效果
ff : 有,但是没效果
chrome : 没有setCapture() 所以用的时候首先要判断元素有没有setCapture()
if ( obj.setCapture ) {
oDiv.setCapture();
} 当鼠标抬起的时候也要释放全局捕获 releaseCapture(); 所以拖拽的时候,如果有文字被选中,我们可以阻止文字的默认事件或者是利用全局捕获将所有的事件都截取到obj上,这样文字不会触发事件:
<style>
#div1 {width: 100px; height: 100px; background: red; position: absolute;}
</style>
<script>
window.onload = function() { var oDiv = document.getElementById('div1'); oDiv.onmousedown = function(ev) {
var ev = ev || event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; if ( oDiv.setCapture ) {
oDiv.setCapture();
} document.onmousemove = function(ev) {
var ev = ev || event; oDiv.style.left = ev.clientX - disX + 'px';
oDiv.style.top = ev.clientY - disY + 'px';
} document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
//释放全局捕获 releaseCapture();
if ( oDiv.releaseCapture ) {
oDiv.releaseCapture();
}
} return false; } }
</script>
</head> <body>
jafldsfjdsjfkl
<div id="div1"></div>
</body>
</html>
这就是拖拽的一个最基本的实现。
拖拽的封装 drag(obj);
<style>
#div1 {width: 100px; height: 100px; background: red; position: absolute;}
#img1 { position: absolute;}
</style>
<script>
window.onload = function() { var oDiv = document.getElementById('div1');
var oImg = document.getElementById('img1'); drag(oImg);
drag(oDiv);
function drag(obj) { obj.onmousedown = function(ev) {
var ev = ev || event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; if ( obj.setCapture ) {
obj.setCapture();
} document.onmousemove = function(ev) {
var ev = ev || event; obj.style.left = ev.clientX - disX + 'px';
obj.style.top = ev.clientY - disY + 'px';
} document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
//释放全局捕获 releaseCapture();
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
} return false; } } }
</script>
</head> <body>
<div id="div1"></div>
<img src="1.jpg" id="img1" />
</body>
</html>
限制范围的拖拽: 先判断值,再赋值。
<style>
#div1 {width: 100px; height: 100px; background: red; position: absolute;}
#img1 { position: absolute;}
</style>
<script>
window.onload = function() { var oDiv = document.getElementById('div1');
var oImg = document.getElementById('img1'); drag(oImg); drag(oDiv); function drag(obj) { obj.onmousedown = function(ev) {
var ev = ev || event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; if ( obj.setCapture ) {
obj.setCapture();
} document.onmousemove = function(ev) {
var ev = ev || event; var L = ev.clientX - disX;
var T = ev.clientY - disY; if ( L < 0 ) {
L = 0;
} else if ( L > document.documentElement.clientWidth - obj.offsetWidth ) {
L = document.documentElement.clientWidth - obj.offsetWidth;
} if ( T < 0 ) {
T = 0;
} else if ( T > document.documentElement.clientHeight - obj.offsetHeight ) {
T = document.documentElement.clientHeight - obj.offsetHeight;
} obj.style.left = L + 'px';
obj.style.top = T + 'px'; } document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
} return false; } } }
</script>
</head> <body>
<div id="div1"></div>
<img src="1.jpg" id="img1" />
</body>
</html>
有一种磁性吸附的效果:
if ( L < ) {
L = 0;
} else if ( L > document.documentElement.clientWidth - obj.offsetWidth ) {
L = document.documentElement.clientWidth - obj.offsetWidth;
}
碰撞检测实例
<style>
#div1 {width: 100px; height: 100px; background: red; position: absolute; z-index: 2;}
#img1 { position: absolute; left: 500px; top: 200px;}
</style>
<script>
window.onload = function() { var oDiv = document.getElementById('div1');
var oImg = document.getElementById('img1'); drag(oDiv); function drag(obj) { obj.onmousedown = function(ev) {
var ev = ev || event; var disX = ev.clientX - this.offsetLeft;
var disY = ev.clientY - this.offsetTop; if ( obj.setCapture ) {
obj.setCapture();
} document.onmousemove = function(ev) {
var ev = ev || event; var L = ev.clientX - disX;
var T = ev.clientY - disY; var L1 = L;
var R1 = L + obj.offsetWidth;
var T1 = T;
var B1 = T + obj.offsetHeight; var L2 = oImg.offsetLeft;
var R2 = L2 + oImg.offsetWidth;
var T2 = oImg.offsetTop;
var B2 = T2 + oImg.offsetHeight; if ( R1 < L2 || L1 > R2 || B1 < T2 || T1 > B2 ) {
oImg.src = '1.jpg';
} else {
oImg.src = '2.jpg';
} obj.style.left = L + 'px';
obj.style.top = T + 'px'; } document.onmouseup = function() {
document.onmousemove = document.onmouseup = null;
if ( obj.releaseCapture ) {
obj.releaseCapture();
}
} return false; } } }
</script>
</head> <body>
<div id="div1"></div>
<img src="1.jpg" id="img1" />
</body>
</html>
JS拖拽原理的更多相关文章
- js拖拽原理和碰撞原理
拖拽的原理onmousedown 选择元素onmousemove 移动元素onmouseup 释放元素 1:如果拖拽的时候有文字:被选中,会产生问题原因:当鼠标按下的时如果页面中有文字或者图片被选中的 ...
- js拖拽原理及简单实现(渣渣自学)
第一步 首先简单分析下需求吧,我们就是想实现鼠标拖拽带颜色的方块时,让方块停留在鼠标松开的位置,需要计算的就是拖拽前的坐标和拖拽后的坐标,鼠标移动后相对于原位置的偏移量=目标元素的偏移量,根据这个等式 ...
- js拖拽效果的实现及原理
元素拖拽分成3个步骤:按下鼠标,移动鼠标,松开鼠标. 拖拽原理:按下拖拽元素后开始监听文档中鼠标移动事件,然后再监听鼠标松开事件:鼠标移动时,元素div要随着鼠标一起移动,需要计算元素div位移的距离 ...
- 一步一步实现JS拖拽插件
js拖拽是常见的网页效果,本文将从零开始实现一个简单的js插件. 一.js拖拽插件的原理 常见的拖拽操作是什么样的呢?整过过程大概有下面几个步骤: 1.用鼠标点击被拖拽的元素 2.按住鼠标不放,移动鼠 ...
- 再谈React.js实现原生js拖拽效果
前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...
- React.js实现原生js拖拽效果及思考
一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...
- js拖拽效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 关于 JS 拖拽功能的冲突问题及解决方法
前言 我在之前写过关于 JS 拖拽的文章,实现方式和网上能搜到的方法大致相同,别无二致,但是在一次偶然的测试中发现,这种绑定事件的方式可能会和其它的拖拽事件产生冲突,由此产生了对于事件绑定的思考.本文 ...
- js拖拽分析
js拖拽分析 思路 1.三个鼠标事件,mousedown,mousemove,mouseup 2.可移动性absolute 3.边界限制 得到鼠标点击处和div边界的距离,然后得出top 和 left ...
随机推荐
- Android多媒体-人脸识别
1. 相关背景 Google 于2006年8月收购Neven Vision 公司 (该公司拥有 10 多项应用于移动设备领域的图像识别的专利),以此获得了图像识别的技术,并不是常快应用到免费的 Pic ...
- 离线安装Cloudera Manager5.3.4与CDH5.3.4(二)
Cloudera Manager Server和Agent所有后发先至.也能够进行CDH5的安装和配置. 然后,主节点可以通过浏览器访问7180port测试(因为CM Server需要花时间来启动,可 ...
- php中用户自定义排序
php中数组用户自定义排序函数有usort和uasort,前者键值重新排列,后者保持原数组的键值. 举例usrot: usort($filterArr, 'sortArr'); function so ...
- 设计模式之Composite模式(笔记)
组合模式:将对象组合成树形结构以表示"部分-总体"的层次结构. 组合模式使得用户对单个对象和组合对象的使用具有一致性. 适用场合:当需求中是体现部分与总体层次的结构时,以及希望用户 ...
- 五、Socket之UDP异步传输文件-实现传输中取消传送
上一篇文章四.Socket之UDP异步传输文件中,只实现了传输开始前拒绝接收文件,没有实现文件传输进行的时候取消传送,这篇文章中我们就来介绍怎样实现这个功能. 在传输过程中取消文件的传送,有很多地方要 ...
- c/c++编译原理
转载自:http://blog.csdn.net/chengocean/article/details/6250779C源程序-->预编译处理(.c)-->编译.优化程序(.s..asm) ...
- windows下回车与换行符
windows下回车与换行符 从键盘输入的数据一般是ASCII码,也就是文本文件,在送到计算机内存时,回车和换行符转换成一个换行符(也就是说回车和换行符在windows文本中是两个字符),再从内存中以 ...
- [未完成]关于枚举(Enum)
今天总结一下枚举相关的知识.先附一段关于枚举的代码: package org.talend.core.model.param; import org.talend.core.i18n.Messages ...
- 20160506-hibernate入门
HQL和Criteria HQL(Hibernate Query Language) 面向对象的查询语言,与SQL不同,HQL中的对象名是区分大小写的(除了JAVA类和属性其他部分不区分大小写):HQ ...
- 未完待续的JAVA基础知识
第二卷 1.每个JAVA程序必须有一个main函数,但并非是每个类都有,main函数必须声明为static函数. 2.println与print之间的区别是换行与不换行. 3.在JAVA中,不想C/C ...