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 相关文章推荐
javascript之AJAX框架使用说明
Apr 24 Javascript
javascript奇异的arguments分析
Oct 20 Javascript
Extjs TimeField 显示正常时间格式的代码
Jun 28 Javascript
javascript页面加载完执行事件代码
Feb 11 Javascript
AngularJs根据访问的页面动态加载Controller的解决方案
Feb 04 Javascript
JavaScript事件详细讲解
Jun 27 Javascript
BootStrap初学者对弹出框和进度条的使用感觉
Jun 27 Javascript
JavaScript动态添加css样式和script标签
Jul 19 Javascript
JS移动端/H5同时选择多张图片上传并使用canvas压缩图片
Jun 20 Javascript
BootStrap Table实现server分页序号连续显示功能(当前页从上一页的结束序号开始)
Sep 12 Javascript
详解在vue-cli项目下简单使用mockjs模拟数据
Oct 19 Javascript
Vue 请求传公共参数的操作
Jul 31 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/10/09 PHP
从Web查询数据库之PHP与MySQL篇
2009/09/25 PHP
php中关于普通表单多文件上传的处理方法
2011/03/25 PHP
JoshChen_web格式编码UTF8-无BOM的小细节分析
2013/08/16 PHP
PHP函数addslashes和mysql_real_escape_string的区别
2014/04/22 PHP
PHP 使用二进制保存用户状态的实例
2018/01/29 PHP
获取当前网页document.url location.href区别总结
2008/05/10 Javascript
IE与Firefox在JavaScript上的7个不同写法小结
2009/09/14 Javascript
JS页面延迟执行一些方法(整理)
2013/11/11 Javascript
Jquery方式获取iframe页面中的 Dom元素
2014/05/07 Javascript
jQuery中:button选择器用法实例
2015/01/04 Javascript
快速掌握Node.js之Window下配置NodeJs环境
2016/03/21 NodeJs
基于jquery实现轮播特效
2016/04/22 Javascript
jQuery编写网页版2048小游戏
2017/01/06 Javascript
windows下vue-cli及webpack搭建安装环境
2017/04/25 Javascript
深入koa-bodyparser原理解析
2019/01/16 Javascript
[03:43]TI9战队采访——PSG.LGD
2019/08/22 DOTA
python 将数据保存为excel的xls格式(实例讲解)
2018/05/03 Python
Django如何防止定时任务并发浅析
2019/05/14 Python
Python单链表原理与实现方法详解
2020/02/22 Python
Jupyter notebook运行Spark+Scala教程
2020/04/10 Python
django-orm F对象的使用 按照两个字段的和,乘积排序实例
2020/05/18 Python
Python 按比例获取样本数据或执行任务的实现代码
2020/12/03 Python
css3实现背景模糊的三种方式(小结)
2020/05/15 HTML / CSS
FOREO官方网站:LUNA露娜洁面仪
2016/11/28 全球购物
解释一下ruby中的特殊方法与特殊类
2013/02/26 面试题
应届生文秘专业个人自荐信格式
2013/09/21 职场文书
企业项目策划书
2014/01/11 职场文书
保护环境倡议书
2014/04/14 职场文书
演讲稿格式
2014/04/30 职场文书
大学生档案自我鉴定(2篇)
2014/10/14 职场文书
故意杀人罪辩护词
2015/05/21 职场文书
2016年春节慰问信息大全
2015/11/30 职场文书
教师反邪教心得体会
2016/01/15 职场文书
四年级数学教学反思
2016/02/16 职场文书
JavaScript圣杯布局与双飞翼布局实现案例详解
2022/08/05 Javascript