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 相关文章推荐
广告切换效果(缓动切换)
May 27 Javascript
javascript firefox 自动加载iframe 自动调整高宽示例
Aug 27 Javascript
jquery 提示信息显示后自动消失的具体实现
Dec 18 Javascript
js判断移动端是否安装某款app的多种方法
Dec 18 Javascript
JavaScript的设计模式经典之建造者模式
Feb 24 Javascript
基于JavaScript实现文字超出部分隐藏
Feb 29 Javascript
Bootstrap Table使用整理(四)之工具栏
Jun 09 Javascript
使用JavaScript解析URL的方法示例
Mar 01 Javascript
微信公众平台 客服接口发消息的实现代码(Java接口开发)
Apr 17 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
May 17 jQuery
使用vuex存储用户信息到localStorage的实例
Nov 11 Javascript
微信小程序跨页面数据传递事件响应实现过程解析
Dec 19 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脚本的10个技巧(5)
2006/10/09 PHP
php split汉字
2009/06/05 PHP
PHP URL路由类实例
2013/11/12 PHP
利用PHP将图片转换成base64编码的实现方法
2016/09/13 PHP
php注册和登录界面的实现案例(推荐)
2016/10/24 PHP
PhpStorm配置Xdebug调试的方法步骤
2019/02/02 PHP
JavaScript监测ActiveX控件是否已经安装过的代码
2008/09/02 Javascript
jMessageBox 基于jQuery的窗口插件
2009/12/09 Javascript
js 代码优化点滴记录
2012/02/19 Javascript
深入理解javascript的执行顺序
2014/04/04 Javascript
再谈JavaScript线程
2015/07/10 Javascript
全面详细的jQuery常见开发技巧手册
2016/02/21 Javascript
JS图片放大效果简单实现代码
2016/09/08 Javascript
jquery Ajax 全局调用封装实例详解
2017/01/16 Javascript
Bootstrap路径导航与分页学习使用
2017/02/08 Javascript
jQuery插件FusionCharts绘制ScrollColumn2D图效果示例【附demo源码下载】
2017/03/22 jQuery
Vue2.0权限树组件实现代码
2017/08/29 Javascript
vue2.0+koa2+mongodb实现注册登录
2018/04/10 Javascript
Vue-cli@3.0 插件系统简析
2018/09/05 Javascript
JavaScript 如何计算文本的行数的实现
2020/09/14 Javascript
vue 数据遍历筛选 过滤 排序的应用操作
2020/11/17 Javascript
python代理工具mitmproxy使用指南
2019/07/04 Python
Python操作Mongodb数据库的方法小结
2019/09/10 Python
Python 如何操作 SQLite 数据库
2020/08/17 Python
Python爬虫抓取论坛关键字过程解析
2020/10/19 Python
阿玛尼美妆加拿大官方商城:Giorgio Armani Beauty加拿大
2017/10/24 全球购物
个人简历中的自我评价范例
2013/10/29 职场文书
校园活动策划书范文
2014/01/10 职场文书
出国留学经济担保书
2014/04/01 职场文书
留学经费担保书
2014/05/12 职场文书
英语专业毕业生求职信
2014/05/24 职场文书
2014年企业工会工作总结
2014/11/12 职场文书
个性与发展自我评价
2015/03/06 职场文书
道歉情书大全
2015/05/12 职场文书
redis复制有可能碰到的问题汇总
2022/04/03 Redis
Spring Data JPA框架持久化存储数据到数据库
2022/04/28 Java/Android