javascript 事件处理、鼠标拖动效果实现方法详解


Posted in Javascript onMay 11, 2012

先看看要拖动的层(模拟窗口)的效果图吧。

javascript 事件处理、鼠标拖动效果实现方法详解
要实现的拖动效果:鼠标左键在窗口上方的标题栏上按下,同时移动鼠标,窗口跟着移动。
窗口:

<div id="win"> 
<div id="win_header"></div> 
</div>

一点准备工作:
要让窗口能自由移动,那么窗口的定位(position)应该采用绝对定位(absolute);
给窗口添加标题栏,这里使用一个放在窗口顶部的层实现,同时将标题栏的鼠标光标设置为拖动(move)形状(在chrome中拖动的时候,光标会变成文字光标,松开鼠标键后恢复)。
#win { 
position:absolute; 
width:480px; 
height:320px; 
background-color:#d4d4d4; 
border: 1px solid #4d4d4d; 
} 
#win_header { 
width:480px; 
height:48px; 
background-color:#4d4d4d; 
cursor:move; 
}

定义一个工具函数,用来获取指定ID属性的元素:
function $id(id) { 
return document.getElementById(id); 
}

定义一个浏览器核心标识isIE:
var isIE = (window.navigator.userAgent.indexOf("IE") == -1) ? false : true;
获取到窗口元素及其标题栏:
var win = $id("win"); 
var header = $id("win_header");

为了方便记录鼠标和窗口的位置信息,创建一个位置:
var pos =function(x, y) { 
this.x = x; 
this.y = y; 
};

给窗口设置一个初始位置(css的left值和top值)。
这里不知道是为什么,如果不使用js设置这两个属性,就取不到值,在CSS中指定了也不行。
var originalpos = new pos(20, 20);

在拖动窗口的过程中,需要记录的值有:
鼠标按下时鼠标光标的位置
var oldmouse =new pos(0, 0);

鼠标按下时窗口的位置
var oldpos = new pos(0, 0);
鼠标移动时窗口的新的位置
var newpos = new pos(0, 0);
设置窗口的初始位置
win.style.left = originalpos.x + "px"; 
win.style.top = originalpos.y + "px";

又是因为浏览器的差异(IE和非IE),元素绑定事件处理函数的方法不同(IE使用attachEvent,非IE使用addEventListener),为了简化事件绑定的操作,定义一个事件绑定函数:
function bind(ev, func) { 
if(isIE) { 
header.attachEvent("on" + ev, func); 
} else { 

header.addEventListener(ev, func, false); 
} 
}

在做好这些工作后,就可以开始处理鼠标事件了。
在这个程序中,只希望鼠标左键拖动窗口,其它键都不能,所以需要判断是否是鼠标左键按下。而这个判断会在几个函数中都使用到,所以提取出来到一个函数中,通过传入的参数(鼠标键值,即按下了哪个键)判断。在这里,需要注意浏览器间的差异:IE中鼠标左键的值是1,而非IE中值是0.
function isLeftButton(btn) { 
if(isIE) { 
if(btn == 1) 
return true; 
else 
return false; 
} else { 
if(btn == 0) 
return true; 
else 
return false; 
} 
}

拖动动作是在按下鼠标左键后移动来完成的。把这个动作分享开来,即是鼠标先触发了按下动作(mousedown),然后触发了移动动作(mousemove)。为了判断是否是真的在拖动还是只是鼠标从窗口上经过,设置一个变量来记录鼠标按下的状态:
var mousedown = false;
由于CSS中存在的兼容性问题,这里使用js来控制鼠标悬停在窗口标题栏上面的时候的颜色变化。
悬浮
function over(e){ 
header.style.backgroundColor = "#5d5d5d"; 
}

离开
function out(e) { 
header.style.backgroundColor = "#4d4d4d"; 
// 有时候鼠标会在未松开的情况下离开窗口, 
// 此时通过触发鼠标的松开事件来使窗口脱离鼠标的控制 
up(e); 
}

按下
在按下事件中,需要先判断是否按下的是鼠标的左键;
若是才记录鼠标和窗口此时的位置,否则不记录。
function down(e) { 
e = e || event; 
if(!isLeftButton(e.button)) 
return; 
mousedown = true; 
oldmouse.x = e.clientX; 
oldmouse.y = e.clientY; 
oldpos.x = parseInt(win.style.left.replace("px", "")); 
oldpos.y = parseInt(win.style.top.replace("px", "")); 
}

松开
function up(e) { 
if(!isLeftButton(e.button)) 
return; 
mousedown = false; 
}

移动
这里就涉及到鼠标的两个事件:
按下和移动。当且仅当鼠标左键按下时,移动动作才有效。
窗口的新位置,是由鼠标在拖动状态下的移动距离(X和Y的距离)决定的。即:
新的鼠标位置送去按下左键时记录下的位置,得到一个距离,然后将窗口的位置加上鼠标移动的距离得到窗口的新位置。
function move(e) { 
if(!isLeftButton(e.button)) 
return; 
if(mousedown) { 
e =e || event; 
newpos.x = e.clientX - oldmouse.x; 
newpos.y = e.clientY - oldmouse.y 
win.style.left = (oldpos.x + newpos.x) + "px"; 
win.style.top = (oldpos.y + newpos.y) + "px"; 
} 
}

事件处理都写好了,最后来给元素绑定上吧,阿门!
bind("mouseover", over); 
bind("mouseenter", over); 
bind("mouseout", out); 
bind("mouseleave", out); 
bind("blur", out); 
bind("mousedown", down); 
bind("mouseup", up); 
bind("mousemove", move);

不过在FF中的拖动有问题,只能第一次正常拖动,后面就有点乱了!
Javascript 相关文章推荐
JavaScript 申明函数的三种方法 每个函数就是一个对象(一)
Dec 04 Javascript
jQuery常见开发技巧详细整理
Jan 02 Javascript
jQuery实现页面下拉100像素出现悬浮窗口的方法
Sep 05 Javascript
jQuery实现对象转为url参数的方法
Jan 11 Javascript
解决Jstree 选中父节点时被禁用的子节点也会选中的问题
Dec 27 Javascript
原生JS实现$.param() 函数的方法
Aug 10 Javascript
vue-better-scroll 的使用实例代码详解
Dec 03 Javascript
javascript中call()、apply()的区别
Mar 21 Javascript
react quill中图片上传由默认转成base64改成上传到服务器的方法
Oct 30 Javascript
three.js 制作动态二维码的示例代码
Jul 31 Javascript
小程序实现密码输入框
Nov 16 Javascript
jQuery实现容器间的元素拖拽功能
Dec 01 jQuery
通过百度地图获取公交线路的站点坐标的js代码
May 11 #Javascript
疯狂Jquery第一天(Jquery学习笔记)
May 11 #Javascript
jQuery 过滤not()与filter()实例代码
May 10 #Javascript
jQuery 在光标定位的地方插入文字的插件
May 10 #Javascript
javascript 在firebug调试时用console.log的方法
May 10 #Javascript
jQueryUI写一个调整分类的拖放效果实现代码
May 10 #Javascript
基于jQuery捕获超链接事件进行局部刷新代码
May 10 #Javascript
You might like
php 验证码制作(网树注释思想)
2009/07/20 PHP
PHP三元运算符的结合性介绍
2012/01/10 PHP
php中如何执行linux命令详解
2018/11/06 PHP
PHP中Static(静态)关键字功能与用法实例分析
2019/04/05 PHP
javascript firefox兼容ie的dom方法脚本
2008/05/18 Javascript
JavaScript学习点滴 call、apply的区别
2010/10/22 Javascript
用Jquery选择器计算table中的某一列某一行的合计
2014/08/13 Javascript
微信小程序 action-sheet底部菜单详解
2016/10/27 Javascript
微信小程序开发之实现选项卡(窗口顶部TabBar)页面切换
2016/11/25 Javascript
关于Vue.js一些问题和思考学习笔记(1)
2016/12/02 Javascript
Canvas实现放射线动画效果
2017/02/15 Javascript
微信小程序开发之IOS和Android兼容的问题
2017/09/26 Javascript
jQuery代码优化方法总结
2018/01/29 jQuery
浅谈VUE防抖与节流的最佳解决方案(函数式组件)
2019/05/22 Javascript
Vue动态加载图片在跨域时无法显示的问题及解决方法
2020/03/10 Javascript
vue+render+jsx实现可编辑动态多级表头table的实例代码
2020/04/01 Javascript
[45:10]NB vs Liquid Supermajor小组赛 A组胜者组决赛 BO3 第二场 6.2
2018/06/04 DOTA
[01:59]翻天覆地,因你而变,7.20版本地图更新速览
2018/11/24 DOTA
Python中解析JSON并同时进行自定义编码处理实例
2015/02/08 Python
Python中Continue语句的用法的举例详解
2015/05/14 Python
利用Python实现Windows下的鼠标键盘模拟的实例代码
2017/07/13 Python
查看Python依赖包及其版本号信息的方法
2019/08/13 Python
python标识符命名规范原理解析
2020/01/10 Python
HTML5 和小程序实现拍照图片旋转、压缩和上传功能
2018/10/08 HTML / CSS
Hotels.com印度:酒店预订
2019/05/11 全球购物
Linux如何修改文件和文件夹的权限
2013/09/05 面试题
文秘专业应届生求职信范文
2013/11/14 职场文书
员工拾金不昧表扬信
2014/01/09 职场文书
《一个中国孩子的呼声》教学反思
2014/02/12 职场文书
导游个人求职信
2014/04/25 职场文书
车间安全生产管理制度
2015/08/06 职场文书
什么是求职信?求职信应包含哪些内容?
2019/08/14 职场文书
Pytorch 实现变量类型转换
2021/05/17 Python
React forwardRef的使用方法及注意点
2021/06/13 Javascript
Java面试题冲刺第十八天--Spring框架3
2021/08/07 面试题
MySQL数据库事务的四大特性
2022/04/20 MySQL