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 相关文章推荐
通过JAVAScript实现页面自适应
Jan 19 Javascript
web的各种前端打印方法之jquery打印插件jqprint实现网页打印
Jan 09 Javascript
JavaScript实现GriwView单列全选(自写代码)
May 13 Javascript
jQuery之自动完成组件的深入解析
Jun 19 Javascript
js动态修改整个页面样式达到换肤效果
May 23 Javascript
jquery实现倒计时代码分享
Jun 13 Javascript
JQuery表格拖动调整列宽效果(自己动手写的)
Sep 01 Javascript
JavaScript学习笔记之Cookie对象
Jan 22 Javascript
smartupload实现文件上传时获取表单数据(推荐)
Dec 12 Javascript
jQuery Masonry瀑布流布局神器使用详解
May 25 jQuery
详解如何理解vue的key属性
Apr 14 Javascript
Vue中通过Vue.extend动态创建实例的方法
Aug 13 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
PHP_MySQL教程-第一天
2007/03/18 PHP
php数据入库前清理 注意php intval与mysql的int取值范围不同
2010/12/12 PHP
php利用单例模式实现日志处理类库
2014/02/10 PHP
PHP读书笔记_运算符详解
2016/07/01 PHP
PHP遍历目录文件的常用方法小结
2017/02/03 PHP
Laravel 手动开关 Eloquent 修改器的操作方法
2019/12/30 PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
2020/02/21 PHP
几个高效,简洁的字符处理函数
2007/04/12 Javascript
jQuery控制图片的hover效果(smartRollover.js)
2012/03/18 Javascript
js字符串完全替换函数分享
2014/12/03 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
2015/03/14 Javascript
JavaScript 事件绑定及深入
2015/04/13 Javascript
jquery获取table指定行和列的数据方法(当前选中行、列)
2016/11/07 Javascript
JavaScript实现PC端横向轮播图
2020/02/07 Javascript
原生JavaScript写出Tabs标签页的实例代码
2020/07/20 Javascript
vue键盘事件点击事件加native操作
2020/07/27 Javascript
使用IronPython把Python脚本集成到.NET程序中的教程
2015/03/31 Python
python动态参数用法实例分析
2015/05/25 Python
详解Python字符串对象的实现
2015/12/24 Python
Python用模块pytz来转换时区
2016/08/19 Python
详解tensorflow训练自己的数据集实现CNN图像分类
2018/02/07 Python
Python爬虫框架Scrapy实例代码
2018/03/04 Python
在Mac上删除自己安装的Python方法
2018/10/29 Python
Django 模型类(models.py)的定义详解
2019/07/19 Python
python路径的写法及目录的获取方式
2019/12/26 Python
Python多线程实现支付模拟请求过程解析
2020/04/21 Python
Win 10下Anaconda虚拟环境的教程
2020/05/18 Python
Python提取视频中图片的示例(按帧、按秒)
2020/10/22 Python
python入门教程之基本算术运算符
2020/11/13 Python
详解Django中的FBV和CBV对比分析
2021/03/01 Python
html5实现滑块功能之type=&quot;range&quot;属性
2020/02/18 HTML / CSS
利用异或运算实现两个无符号数的加法运算
2013/12/20 面试题
社区文化建设方案
2014/05/02 职场文书
体育口号大全
2014/06/18 职场文书
Python基础详解之描述符
2021/04/28 Python
VUE之图片Base64编码使用ElementUI组件上传
2022/04/09 Vue.js