javascript动画之模拟拖拽效果篇

作者:小火柴的蓝色理想 时间:2024-04-16 09:14:22 

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

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,拖拽
0
投稿

猜你喜欢

  • Python做文本按行去重的实现方法

    2021-12-31 17:41:07
  • 基于Django框架的rest_framework的身份验证和权限解析

    2021-02-21 23:42:58
  • python中的正则表达式,贪婪匹配与非贪婪匹配方式

    2023-04-04 18:37:36
  • Python使用wget实现下载网络文件功能示例

    2022-04-28 03:27:46
  • python练习之曾经很火的小人画爱心表白代码

    2023-03-16 19:11:50
  • python re模块findall()函数实例解析

    2022-07-07 13:38:40
  • Python中将字典转换为XML以及相关的命名空间解析

    2022-07-22 20:05:03
  • 浅析SQL Server中包含事务的存储过程

    2024-01-15 21:27:39
  • MySQL是如何实现主备同步

    2024-01-19 06:53:16
  • python银行卡号码校验Luhn模10算法

    2022-03-18 07:32:52
  • 程序员的八种境界,你在哪一境?

    2022-07-19 11:22:19
  • MySQL如何统计一个数据库所有表的数据量

    2024-01-23 20:07:14
  • 如何把数据从SQL Server导出到Access或Excel中去?

    2009-11-02 20:26:00
  • Python中除法使用的注意事项

    2021-11-07 07:18:17
  • Python如何一行输入多个数,并存入列表

    2023-09-27 19:14:56
  • 如何理解Python中包的引入

    2021-08-14 11:42:31
  • python函数装饰器之带参数的函数和带参数的装饰器用法示例

    2022-02-14 08:43:40
  • 使用Python制作自动推送微信消息提醒的备忘录功能

    2023-02-26 18:19:40
  • 在CentOS系统上从零开始搭建WordPress博客的全流程记录

    2024-04-28 09:19:26
  • SQL Server触发器及触发器中的事务学习

    2024-01-27 08:48:02
  • asp之家 网络编程 m.aspxhome.com