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 相关文章推荐
ext实现完整的登录代码
Aug 08 Javascript
jquery中ajax学习笔记3
Oct 16 Javascript
从URL中提取参数与将对象转换为URL查询参数的实现代码
Jan 12 Javascript
jquery sortable的拖动方法示例详解
Jan 16 Javascript
js中的for如何实现foreach中的遍历
May 31 Javascript
容易造成JavaScript内存泄露几个方面
Sep 04 Javascript
在JavaScript中操作时间之setYear()方法的使用
Jun 12 Javascript
浅谈jquery选择器 :first与:first-child的区别
Nov 20 Javascript
vue-cli脚手架搭建的项目去除eslint验证的方法
Sep 29 Javascript
在Vue项目中用fullcalendar制作日程表的示例代码
Aug 04 Javascript
Vue实现商品详情页的评价列表功能
Sep 04 Javascript
layer弹出框确定前验证:弹出消息框的方法(弹出两个layer)
Sep 21 Javascript
通过百度地图获取公交线路的站点坐标的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 编程请选择正确的文本编辑软件
2006/12/21 PHP
WINDOWS下php5.2.4+mysql6.0+apache2.2.4+ZendOptimizer-3.3.0配置
2008/03/28 PHP
ThinkPHP模板替换与系统常量及应用实例教程
2014/08/22 PHP
如何动态的导入js文件具体该怎么实现
2014/01/14 Javascript
PhotoShop给图片自动添加边框及EXIF信息的JS脚本
2015/02/15 Javascript
js控制文本框只输入数字和小数点的方法
2015/03/10 Javascript
jQuery对象与DOM对象转换方法详解
2016/05/10 Javascript
jQuery数据检索中根据关键字快速定位GridView指定行的实现方法
2016/06/08 Javascript
利用js判断手机是否安装某个app的多种方案
2017/02/13 Javascript
详解打造 Vue.js 可复用组件
2017/03/24 Javascript
通过命令行生成vue项目框架的方法
2017/07/12 Javascript
cocos creator Touch事件应用(触控选择多个子节点的实例)
2017/09/10 Javascript
详解webpack 打包文件体积过大解决方案(code splitting)
2018/04/10 Javascript
详解Vue中的基本语法和常用指令
2019/07/23 Javascript
vue-cli4.x创建企业级项目的方法步骤
2020/06/18 Javascript
antd vue table跨行合并单元格,并且自定义内容实例
2020/10/28 Javascript
使用Vant完成Dialog弹框案例
2020/11/11 Javascript
layui使用及简单的三级联动实现教程
2020/12/01 Javascript
在vue中使用inheritAttrs实现组件的扩展性介绍
2020/12/07 Vue.js
零基础写python爬虫之HTTP异常处理
2014/11/05 Python
python中zip()方法应用实例分析
2016/04/16 Python
使用Python的package机制如何简化utils包设计详解
2017/12/11 Python
Python实现按中文排序的方法示例
2018/04/25 Python
python实现自动登录
2018/09/17 Python
使用python Fabric动态修改远程机器hosts的方法
2018/10/26 Python
Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)
2020/07/06 Python
python如何获得list或numpy数组中最大元素对应的索引
2020/11/16 Python
英国经典球衣网站:Classic Football Shirts
2017/05/20 全球购物
理肤泉英国官网:La Roche-Posay英国
2019/01/14 全球购物
英文简历自荐信范文
2013/12/11 职场文书
实习自我鉴定
2013/12/15 职场文书
小学生放飞梦想演讲稿
2014/08/26 职场文书
党的群众路线教育实践活动批评与自我批评范文
2014/10/16 职场文书
初中历史教学反思
2016/02/19 职场文书
Windows下用Nginx配置https服务器及反向代理的问题
2021/09/25 Servers
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL