javascript动画之模拟拖拽效果篇

 更新时间:2016年09月26日 15:39:32   作者:小火柴的蓝色理想  
其实javascript本身是具有原生拖放功能的,但是由于兼容性问题,以及功能实现的方式,用的不是很广泛。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>

代码优化

  使用上面的代码时,会出现一个问题。当鼠标拖动的太快,比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>

拖拽冲突

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

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

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

  只要在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模拟拖拽的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。

相关文章

  • 新手快速入门微信小程序组件库 iView Weapp

    新手快速入门微信小程序组件库 iView Weapp

    这篇文章主要介绍了新手快速入门微信小程序组件库 iView Weapp,iView Weapp 提供了与 iView 一致的 UI 和尽可能相同的接口名称,大幅度降低了学习成本,是一套一套高质量的微信小程序 UI 组件库,需要的朋友可以参考下
    2019-06-06
  • js求数组中全部数字可拼接出的最大整数示例代码

    js求数组中全部数字可拼接出的最大整数示例代码

    这篇文章主要给大家介绍了利用js如何求数组中全部数字可拼接出的最大整数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考借鉴,下面随着小编一起来学习学习吧。
    2017-08-08
  • 详解钉钉小程序组件之自定义模态框(弹窗封装实现)

    详解钉钉小程序组件之自定义模态框(弹窗封装实现)

    这篇文章主要介绍了钉钉小程序组件之自定义模态框(弹窗封装实现)的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 两行代码轻松搞定JavaScript日期验证

    两行代码轻松搞定JavaScript日期验证

    两行代码轻松搞定JavaScript日期验证,通过实例化Date对象来生成一个合法的日期,验证日期是否合法,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • JavaScript之自定义类型

    JavaScript之自定义类型

    在JavaScript中,创建一个具有自定义属性和方法的对象有很多种模式,下面一一进行介绍
    2012-05-05
  • 详解js中let与var声明变量的区别

    详解js中let与var声明变量的区别

    这篇文章主要介绍了let与var声明变量区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-05-05
  • 原生js ActiveXObject获取execl里面的值

    原生js ActiveXObject获取execl里面的值

    使用原生js获取execl里面的值,想必有很多的朋友都不会吧,下面有个不错的方法主要是使用ActiveXObject来实现,感兴趣的朋友可不要错过
    2013-11-11
  • js实现同一页面多个运动效果的方法

    js实现同一页面多个运动效果的方法

    这篇文章主要介绍了js实现同一页面多个运动效果的方法,涉及javascript操作页面元素运动效果的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • js获取select标签的值且兼容IE与firefox

    js获取select标签的值且兼容IE与firefox

    本篇文章主要介绍了js获取select标签的值且兼容IE与firefox。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  •  javascript数组中的slice方法和join​​方法

     javascript数组中的slice方法和join​​方法

    这篇文章主要介绍了 javascript数组中的slice方法和join​​方法,文章内容介绍详细,具有一的参考价值,需要的小伙伴可以参考一下,希望对你的学习有所帮助
    2022-03-03

最新评论