javascript动画之模拟拖拽效果篇


Posted in Javascript onSeptember 26, 2016

先看看实现效果图, 模拟拖拽最终效果和在桌面上移动文件夹的效果类似

javascript动画之模拟拖拽效果篇

原理介绍

鼠标按下时,拖拽开始。鼠标移动时,被拖拽元素跟着鼠标一起移动。鼠标抬起时,拖拽结束

所以,拖拽的重点是确定被拖拽元素是如何移动的

javascript动画之模拟拖拽效果篇

假设,鼠标按下时,鼠标对象的clientX和clientY分别为x1和x2。元素距离视口左上角x轴和y轴分别为x0和y0

鼠标移动的某一时刻,clientX和clientY分别为x2和y2

所以,元素移动的x轴和y轴距离分别为x2-x1和y2-y1

元素移动后,元素距离视口左上角x轴和y轴的位置分别为

X = x0 + (x2-x1)
 Y = y0 + (y2-y1)

代码实现

将上面的原理用代码实现如下

鼠标按下时,初始态的x0和y0分别用offsetLeftoffsetTop表示

鼠标移动时,瞬时态的x和y分别赋值为定位后元素的left和top

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;"></div>
<script>
test.onmousedown = function(e){
 e = e || event;
 //获取元素距离定位父级的x轴及y轴距离
 var x0 = this.offsetLeft;
 var y0 = this.offsetTop;
 //获取此时鼠标距离视口左上角的x轴及y轴距离
 var x1 = e.clientX;
 var y1 = e.clientY;

 test.onmousemove = function(e){
  e = e || event;
  //获取此时鼠标距离视口左上角的x轴及y轴距离
  x2 = e.clientX;
  y2 = e.clientY; 
  //计算此时元素应该距离视口左上角的x轴及y轴距离
  var X = x0 + (x2 - x1);
  var Y = y0 + (y2 - y1);
  //将X和Y的值赋给left和top,使元素移动到相应位置
  test.style.left = X + 'px';
  test.style.top = Y + 'px';
 }

 test.onmouseup = function(e){
  //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
  test.onmousemove = null;
 }
}
</script>

javascript动画之模拟拖拽效果篇

代码优化

使用上面的代码时,会出现一个问题。当鼠标拖动的太快,比onmousemove事件的触发间隔还要快时,鼠标就会从元素上离开。这样就停止了元素的拖拽过程

此时,如果把mousemovemouseup事件都加在document上时,即可解决

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;"></div>
<script>
test.onmousedown = function(e){
 e = e || event;
 //获取元素距离定位父级的x轴及y轴距离
 var x0 = this.offsetLeft;
 var y0 = this.offsetTop;
 //获取此时鼠标距离视口左上角的x轴及y轴距离
 var x1 = e.clientX;
 var y1 = e.clientY;

 document.onmousemove = function(e){
  e = e || event;
  //获取此时鼠标距离视口左上角的x轴及y轴距离
  x2 = e.clientX;
  y2 = e.clientY; 
  //计算此时元素应该距离视口左上角的x轴及y轴距离
  var X = x0 + (x2 - x1);
  var Y = y0 + (y2 - y1);
  //将X和Y的值赋给left和top,使元素移动到相应位置
  test.style.left = X + 'px';
  test.style.top = Y + 'px';
 }

 document.onmouseup = function(e){
  //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
  document.onmousemove = null;
 }
}
</script>

javascript动画之模拟拖拽效果篇

拖拽冲突

由于文字和图片默认支持原生拖放,如果将原生拖放和模拟拖拽掺杂在一起,将造成与预想效果不符的情况

如果拖放的元素内容存在文字,且文字被选中会触发文字的原生拖放效果

在文字上面双击鼠标,即可选中文字,再移动鼠标时,会触发文字的原生拖放效果,如下所示

javascript动画之模拟拖拽效果篇

只要在onmousedown事件阻止浏览器的默认行为即可

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">测试文字</div>
<script>
test.onmousedown = function(e){
 e = e || event;
 //获取元素距离定位父级的x轴及y轴距离
 var x0 = this.offsetLeft;
 var y0 = this.offsetTop;
 //获取此时鼠标距离视口左上角的x轴及y轴距离
 var x1 = e.clientX;
 var y1 = e.clientY;

 document.onmousemove = function(e){
  e = e || event;
  //获取此时鼠标距离视口左上角的x轴及y轴距离
  x2 = e.clientX;
  y2 = e.clientY; 
  //计算此时元素应该距离视口左上角的x轴及y轴距离
  var X = x0 + (x2 - x1);
  var Y = y0 + (y2 - y1);
  //将X和Y的值赋给left和top,使元素移动到相应位置
  test.style.left = X + 'px';
  test.style.top = Y + 'px';
 }

 document.onmouseup = function(e){
  //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
  document.onmousemove = null;
 }
 //阻止默认行为
 return false;
}
</script>

IE兼容

以上代码在IE8-浏览器中仍然无法阻止默认行为。此时,为了实现IE兼容,需要使用全局捕获setCapture()和释放捕获releaseCapture()

首先,先看一下全局捕获的效果

下面代码中,开启全局捕获之后,页面中的所有点击效果,都相当于针对按钮一的点击效果。释放捕获后,效果消失

[注意]IE浏览器完全支持全局捕获;chrome不支持,使用全局捕获会报错;firefox不报错,但静默失败

<button id="btn1">按钮一</button>
<button id="btn2">开启按钮一的全局捕获</button>
<script>
btn1.onclick = function(){
 alert(1);
}
btn2.onclick = function(){
 if(btn1.setCapture){
  if(btn2.innerHTML.charAt(0) == '开'){
   btn1.setCapture();
   btn2.innerHTML = '关闭按钮一的全局捕获';
  }else{
   btn1.releaseCapture();
   btn2.innerHTML = '开启按钮一的全局捕获'; 
  }
 }
}
</script>

通过在IE浏览器设置全局捕获来达到取消文字原生拖放的默认行为

<div id="test" style="height: 100px;width: 100px;background:pink;position:absolute;top:0;left:0;">测试文字</div>
<script>
test.onmousedown = function(e){
 e = e || event;
 //获取元素距离定位父级的x轴及y轴距离
 var x0 = this.offsetLeft;
 var y0 = this.offsetTop;
 //获取此时鼠标距离视口左上角的x轴及y轴距离
 var x1 = e.clientX;
 var y1 = e.clientY;

 document.onmousemove = function(e){
  e = e || event;
  //获取此时鼠标距离视口左上角的x轴及y轴距离
  x2 = e.clientX;
  y2 = e.clientY; 
  //计算此时元素应该距离视口左上角的x轴及y轴距离
  var X = x0 + (x2 - x1);
  var Y = y0 + (y2 - y1);
  //将X和Y的值赋给left和top,使元素移动到相应位置
  test.style.left = X + 'px';
  test.style.top = Y + 'px';
 }

 document.onmouseup = function(e){
  //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
  document.onmousemove = null;
  //释放全局捕获
  if(test.releaseCapture){
   test.releaseCapture();
  }
 }
 //阻止默认行为
 return false;
 //IE8-浏览器阻止默认行为
 if(test.setCapture){
  test.setCapture();
 }
}
</script>

javascript动画之模拟拖拽效果篇

总结

以上就是Javascript模拟拖拽的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

Javascript 相关文章推荐
分享一个我自己写的ToolTip提示插件(附源码)
Jan 20 Javascript
JavaScript也谈内存优化
Jun 06 Javascript
javascript中函数作为参数调用的方法
Feb 09 Javascript
通过JS判断联网类型和连接状态的实现代码
Apr 01 Javascript
使用CamanJS在Web页面上处理图像的技巧
Aug 18 Javascript
jQuery实现淡入淡出二级下拉导航菜单的方法
Aug 28 Javascript
jQuery实现背景弹性滚动的导航效果
Jun 01 Javascript
JavaScript lodash常见用法系列小结
Aug 24 Javascript
JavaScript实现反转字符串的方法详解
Apr 27 Javascript
Vue2.0用户权限控制解决方案的示例
Feb 10 Javascript
JavaScript设计模式之责任链模式实例分析
Jan 16 Javascript
javascript实现抢购倒计时程序
Aug 26 Javascript
微信小程序(应用号)简单实例应用及实例详解
Sep 26 #Javascript
微信小程序 框架详解及实例应用
Sep 26 #Javascript
jQuery中JSONP的两种实现方式详解
Sep 26 #Javascript
javascript的函数劫持浅析
Sep 26 #Javascript
JavaScript中this的四个绑定规则总结
Sep 26 #Javascript
jQuery 选择器(61种)整理总结
Sep 26 #Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 #Javascript
You might like
8个出色的WordPress SEO插件收集
2011/02/26 PHP
通过php修改xml文档内容的方法
2015/01/23 PHP
django中的ajax组件教程详解
2018/10/18 PHP
TP5框架简单登录功能实现方法示例
2019/10/31 PHP
父窗口获取弹出子窗口文本框的值
2006/06/27 Javascript
JavaScript中prototype为对象添加属性的误区介绍
2013/10/15 Javascript
js 页面元素的几个用法总结
2013/11/18 Javascript
javascript实现动态侧边栏代码
2014/02/19 Javascript
纯JavaScript实现获取onclick、onchange等事件的值
2014/12/29 Javascript
jquery果冻抖动效果实现方法
2015/01/15 Javascript
js分页工具实例
2015/01/28 Javascript
JavaScript实现列表分页功能特效
2015/05/15 Javascript
JavaScript实现简单精致的图片左右无缝滚动效果
2017/03/16 Javascript
js判断是否是手机页面
2017/03/17 Javascript
Node.JS利用PhantomJs抓取网页入门教程
2017/05/19 Javascript
javaScript封装的各种写法
2017/08/14 Javascript
微信小程序实现页面跳转传值的方法
2017/10/12 Javascript
基于node+websocket+html实现腾讯课堂聊天室聊天功能
2020/03/04 Javascript
Vue优化:常见会导致内存泄漏问题及优化详解
2020/08/04 Javascript
Js Snowflake(雪花算法)生成随机ID的实现方法
2020/08/26 Javascript
pyhanlp安装介绍和简单应用
2019/02/22 Python
Python数据类型之Dict字典实例详解
2019/05/07 Python
使用Matplotlib 绘制精美的数学图形例子
2019/12/13 Python
python向xls写入数据(包括合并,边框,对齐,列宽)
2021/02/02 Python
浅谈CSS3特性查询(Feature Query: @supports)功能简介
2017/07/31 HTML / CSS
世界上最伟大的马产品:Equiderma
2020/01/07 全球购物
测控技术与仪器个人求职信范文
2013/12/30 职场文书
团队激励口号
2014/06/06 职场文书
小学运动会演讲稿
2014/08/25 职场文书
在宿舍喝酒的检讨书
2014/09/28 职场文书
2014大学校园光棍节活动策划书
2014/09/29 职场文书
通知函的格式
2015/04/27 职场文书
2016年小学优秀班主任事迹材料
2016/02/29 职场文书
详解如何在Canvas中添加事件的方法
2021/04/17 Javascript
SpringBoot全局异常处理方案分享
2022/05/25 Java/Android
Python  序列化反序列化和异常处理的问题小结
2022/12/24 Python