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 相关文章推荐
基于逻辑运算的简单权限系统(实现) JS 版
Mar 24 Javascript
jquery 插件 人性化的消息显示
Jan 21 Javascript
javascript document.compatMode兼容性
Feb 23 Javascript
iframe异步加载实现点击左边菜单加载右边内容实例讲解
Mar 04 Javascript
二叉树的非递归后序遍历算法实例详解
Feb 07 Javascript
node.js中的favicon.ico请求问题处理
Dec 15 Javascript
JavaScrpt中如何使用 cookie 设置查看与删除功能
Jul 09 Javascript
JS实现登录页密码的显示和隐藏功能
Dec 06 Javascript
微信小程序select下拉框实现效果
May 15 Javascript
js实现简易计算器功能
Oct 18 Javascript
jQuery 图片查看器插件 Viewer.js用法简单示例
Apr 04 jQuery
element中el-container容器与div布局区分详解
May 13 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
《心理测量者3》剧场版动画预告
2020/03/02 日漫
PHP 模拟登陆MSN并获得用户信息
2009/05/16 PHP
PHP IDE PHPStorm配置支持友好Laravel代码提示方法
2015/05/12 PHP
PHP数组去重比较快的实现方式
2016/01/19 PHP
总结的一些PHP开发中的tips(必看篇)
2017/03/24 PHP
jQuery validate 中文API 附validate.js中文api手册
2010/07/31 Javascript
EasyUI的treegrid组件动态加载数据问题的解决办法
2011/12/11 Javascript
引入autocomplete组件时JS报未结束字符串常量错误
2014/03/19 Javascript
js实现类似MSN提示的页面效果代码分享
2015/08/24 Javascript
javascript鼠标右键菜单自定义效果
2020/12/08 Javascript
jQuery表格插件datatables用法汇总
2016/03/29 Javascript
详解JSON1:使用TSQL查询数据和更新JSON数据
2016/11/21 Javascript
js鼠标移动时禁止选中文字
2017/02/19 Javascript
Webpack实战加载SVG的方法
2017/12/26 Javascript
vuex与组件联合使用的方法
2018/05/10 Javascript
Vue.js结合bootstrap前端实现分页和排序效果
2018/12/29 Javascript
微信小程序自定义单项选择器样式
2019/07/25 Javascript
浅谈Vue2.4.0 $attrs与inheritAttrs的具体使用
2020/03/08 Javascript
[15:41]教你分分钟做大人——灰烬之灵
2015/03/11 DOTA
基于Python_脚本CGI、特点、应用、开发环境(详解)
2017/05/23 Python
Mac 上切换Python多版本
2017/06/17 Python
Python实现时钟显示效果思路详解
2018/04/11 Python
Python干货:分享Python绘制六种可视化图表
2018/08/27 Python
python输入整条数据分割存入数组的方法
2018/11/13 Python
django 2.2和mysql使用的常见问题
2019/07/18 Python
Django 对IP访问频率进行限制的例子
2019/08/30 Python
Python图像阈值化处理及算法比对实例解析
2020/06/19 Python
Python实现爬取网页中动态加载的数据
2020/08/17 Python
HTML5 UTF-8 中文乱码的解决方法
2013/11/18 HTML / CSS
超市活动计划书
2014/04/24 职场文书
2014年三万活动总结
2014/04/26 职场文书
大学生作弊检讨书
2014/09/11 职场文书
机票销售员态度不好检讨书
2014/09/27 职场文书
药品开票员岗位职责
2015/04/15 职场文书
现实表现证明材料
2015/06/19 职场文书
Javascript中Microtask和Macrotask鲜为人知的知识点
2022/04/02 Javascript