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 相关文章推荐
一个不错的字符串转码解码函数(自写)
Jul 31 Javascript
深入了解Node.js中的一些特性
Sep 25 Javascript
Linux下使用jq友好的打印JSON技巧分享
Nov 18 Javascript
jQuery中ready事件用法实例
Jan 19 Javascript
js实现绿白相间竖向网页百叶窗动画切换效果
Mar 02 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
Aug 05 Javascript
JS原型链 详解及示例代码
Sep 06 Javascript
新闻上下滚动jquery 超简洁(必看篇)
Jan 21 Javascript
Javascript中构造函数要注意的一些坑
Jan 23 Javascript
Layui数据表格之获取表格中所有的数据方法
Aug 20 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
Oct 01 Javascript
详解vue开发中调用微信jssdk的问题
Apr 16 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中header和session_start前不能有输出原因分析
2013/01/11 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
jQuery随便控制任意div隐藏的方法
2013/06/28 Javascript
node.js中的fs.mkdirSync方法使用说明
2014/12/17 Javascript
jQuery在线选座位插件seat-charts特效代码分享
2015/08/27 Javascript
JavaScript学习小结(一)——JavaScript入门基础
2015/09/02 Javascript
iScroll.js 使用方法参考
2016/05/16 Javascript
JS判断字符串变量是否含有某个字串的实现方法
2016/06/03 Javascript
Node.js 日志处理模块log4js
2016/08/28 Javascript
JavaScript中的子窗口与父窗口的互相调用问题
2017/02/08 Javascript
javascript事件的传播基础实例讲解(35)
2017/02/14 Javascript
详解基于vue的移动web app页面缓存解决方案
2017/08/03 Javascript
关于vue单文件中引用路径的处理方法
2018/01/08 Javascript
angularjs实现table增加tr的方法
2018/02/27 Javascript
vue 多入口文件搭建 vue多页面搭建的实例讲解
2018/03/12 Javascript
Vue封装的可编辑表格插件方法
2018/08/28 Javascript
Vuex实现数据增加和删除功能
2019/11/11 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
2020/07/07 Javascript
python3使用tkinter实现ui界面简单实例
2014/01/10 Python
python类装饰器用法实例
2015/06/04 Python
Python实现的桶排序算法示例
2017/11/29 Python
解决Python下imread,imwrite不支持中文的问题
2018/12/05 Python
Django 全局的static和templates的使用详解
2019/07/19 Python
详解python statistics模块及函数用法
2019/10/27 Python
Python如何将装饰器定义为类
2020/07/30 Python
加拿大建筑和装修专家:Reno-Depot
2017/12/21 全球购物
英国旅行箱包和行李箱购物网站:Travel Luggage & Cabin Bags
2019/08/26 全球购物
美国购物网站:Clickhere2shop
2021/01/28 全球购物
Three Graces London官网:英国奢侈品牌
2021/03/18 全球购物
道德大讲堂实施方案
2014/05/14 职场文书
软件售后服务承诺书
2014/05/21 职场文书
上市公司董事长岗位职责
2015/04/16 职场文书
2015年乡镇环保工作总结
2015/04/22 职场文书
爱心捐助活动总结
2015/05/09 职场文书
在JavaScript中如何使用宏详解
2021/05/06 Javascript
简单聊一聊SQL注入及防止SQL注入
2022/03/23 MySQL