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 相关文章推荐
ExtJS 学习专题(一) 如何应用ExtJS(附实例)
Mar 11 Javascript
jQuery学习笔记 操作jQuery对象 文档处理
Sep 19 Javascript
jQuery插件实现表格隔行变色及鼠标滑过高亮显示效果代码
Feb 25 Javascript
AngularJS基础 ng-srcset 指令简单示例
Aug 03 Javascript
canvas时钟效果
Feb 16 Javascript
微信小程序自定义音乐进度条的实例代码
Aug 28 Javascript
vuejs 制作背景淡入淡出切换动画的实例
Sep 01 Javascript
vue使用laydate时间插件的方法
Nov 14 Javascript
详解Vue项目中实现锚点定位
Apr 24 Javascript
layui table 表格上添加日期控件的两种方法
Sep 28 Javascript
js实现简单放大镜效果
Mar 07 Javascript
Angular+ionic实现折叠展开效果的示例代码
Jul 29 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
基于mysql的论坛(7)
2006/10/09 PHP
PHP学习笔记之三 数据库基本操作
2011/01/17 PHP
PHP无限分类代码,支持数组格式化、直接输出菜单两种方式
2011/05/18 PHP
php 批量生成html,txt文件的实现代码
2013/06/26 PHP
Yii框架实现的验证码、登录及退出功能示例
2017/05/20 PHP
laravel dingo API返回自定义错误信息的实例
2019/09/29 PHP
js和jquery如何获取图片真实的宽度和高度
2014/09/28 Javascript
深入探究AngularJS框架中Scope对象的超级教程
2016/01/04 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
2016/01/12 Javascript
基于JS实现发送短信验证码后的倒计时功能(无视页面刷新,页面关闭不进行倒计时功能)
2016/09/02 Javascript
vuejs响应用户事件(如点击事件)
2017/03/14 Javascript
微信小程序实现动态显示和隐藏某个控件功能示例
2018/12/14 Javascript
微信小程序实现元素渐入渐出动画效果封装方法
2019/05/18 Javascript
微信小程序引入Vant组件库过程解析
2019/08/06 Javascript
解决vue+ element ui 表单验证有值但验证失败问题
2020/01/16 Javascript
JavaScript中的几种继承方法示例
2020/12/06 Javascript
简单介绍使用Python解析并修改XML文档的方法
2015/10/15 Python
关于PyTorch 自动求导机制详解
2019/08/18 Python
Django中间件拦截未登录url实例详解
2019/09/03 Python
Python 网络编程之TCP客户端/服务端功能示例【基于socket套接字】
2019/10/12 Python
python实现用户名密码校验
2020/03/18 Python
Vero Moda西班牙官方购物网站:丹麦BESTSELLER旗下知名女装品牌
2018/04/27 全球购物
金属材料工程个人求职的自我评价
2013/12/04 职场文书
大学活动策划书范文
2014/01/10 职场文书
护士毕业自我鉴定
2014/02/07 职场文书
解除劳动合同协议书范本
2014/09/13 职场文书
2015年信息宣传工作总结
2015/05/26 职场文书
2015年暑期见闻
2015/07/14 职场文书
学习师德师风的心得体会(2篇)
2019/10/08 职场文书
JavaScript实现显示和隐藏图片
2021/04/29 Javascript
python 提取html文本的方法
2021/05/20 Python
Python基础学习之奇异的GUI对话框
2021/05/27 Python
MySQL5.7并行复制原理及实现
2021/06/03 MySQL
Python中seaborn库之countplot的数据可视化使用
2021/06/11 Python
Opencv中cv2.floodFill算法的使用
2021/06/18 Python
MySql按时,天,周,月进行数据统计
2022/08/14 MySQL