事件对象
当事件的响应被触发时,浏览器每次都会将一个事件对象作为实参传递给响应函数,在事件对象中封装了当前事件相关的一切信息,比如:鼠标的坐标,键盘哪个按键被按下,鼠标滚轮滚动的方向等。
clientX可以获取鼠标指针的水平坐标
clientY可以获取鼠标指针的垂直坐标
获取鼠标在div里的坐标:
window.onload = function () {
/*
*当鼠标在areaDiv中移动时,在showMsg中来显示鼠标坐标
*/
//获取两个div
var areaDiv = document.getElementById("areaDiv");
var showMsg = document.getElementById("showMsg");
//onmousemove该事件将会在鼠标在元素中移动时被触发
areaDiv.onmousemove = function (event) {
//在showMsg显示鼠标坐标
var x = event.clientX;
var y = event.clientY;
showMsg.innerHTML = "此时鼠标坐标:x="+x+","+"y="+y;
};
};
效果:
在IE8中,事件函数被触发时,浏览器不会传递事件对象,在IE8及以下浏览器中,是将对象作为window对象的属性保存的。
即:
var x = event.clientX;
var y = event.clientY;
应该改为:
var x = window.event.clientX;
var y = window.event.clientY;
但是该方式火狐不兼容,所以应该这么改:
if (!event){
event =window.event;
}
var x = event.clientX;
var y = event.clientY;
也可以
event = event || window.event;
var x = event.clientX;
var y = event.clientY;
使div可以跟随鼠标移动
绑定鼠标移动事件,应该绑定给整个文档,以免鼠标移出div就不再跟随。
document.onmousemove = function(event){}
解决兼容问题后,再获取鼠标的坐标,设置div的偏移量。clientX与clientY获取的是鼠标在当前可见页面的坐标,div的偏移量,是相对于整个页面的,当出现滚动条时,div与鼠标会出现距离。所以应该使用pageX
和pageY
可以获取鼠标相对于当前页面的坐标。
注意:如果想要让偏移量起作用,则需要开启box1的绝对定位。
var left = event.pageX;
var top = event.pageY;
box1.style.left = left + "px";
box1.style.top = top + "px";
但是这两个属性在IE8中并不支持,所以如果想要兼容IE8就不能使用,则可以这样修改。
先获取滚动条的滚动距离
var st = document.body.scrollTop;//chrome
var sl = document.body.scrollLeft;
chrome认为浏览器的滚动条时body的,可以通过body.scrollTop来获取,火狐等浏览器认为浏览器的滚动条是HTML的
var st = document.documentElement.scrollTop;//火狐等浏览器
var sl = document.documentElement.scrollLeft;
处理兼容性问题
var st = document.documentElement.scrollTop || document.body.scrollTop;
var sl = document.documentElement.scrollLeft || document.body.scrollLeft;
最后优化结果
var left = event.clientX;
var top = event.clientY;
box1.style.left = left +sl + "px";
box1.style.top = top +st + "px";
事件的冒泡(Bubble)
所谓的冒泡指的就是事件的向上传导,当后代元素事件被触发时,其祖先元素的相同事件也会被触发。在开发中,大部分情况冒泡都是非常有用的,如果不希望发生事件冒泡,可以通过事件对象来取消冒泡。
将事件对象的cancelBubble设置为true,即可取消冒泡
envent.cancelBubble = true;
事件的委派
事件的委派,指将事件统一绑定给元素的共同的祖先元素,这样当后代元素上的事件触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。如果想要只绑定一次事件,即可应用到多个元素上,即使元素是后添加的,可以尝试将其绑定给元素的共同的祖先元素。
优点:事件的委派时利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。
但是由于设置的面积很大,点击未期望的内容也会触发响应函数。
补充:target表示触发事件的对象。
//当点击的是ul中的class为link的对象则执行响应函数,否则不执行。
if(event.target.className == "link"){
alert("单击响应函数");
}
事件的绑定
使用 对象.事件 = 函数
的形式绑定的响应函数,它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后面的会覆盖掉前面的。
addEventListener()通过这个方法也可以为元素绑定响应函数。
参数:
第一个参数是事件的字符串,不要on;
第二个参数是回调函数,当事件被触发时该函数会被调用;
第三个参数是否在捕获阶段触发事件,需要一个布尔值,一般都传false。
btn.addEventListener("click",function(){
alert(1);
},false);
使用addEventListener()方法可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照函数的绑定顺序执行。
注意:该方法不支持IE8及以下的浏览器
在IE8中可以使用attachEvent()来绑定事件
参数:
第一个参数是事件的字符串,要on
第二个参数是回调函数
btn.attachEvent("onclick",function(){
alert(1);
});
使用attachEvent()方法可以同时为一个元素的相同事件同时绑定多个响应函数,它是后绑定先执行,执行顺序和addEventListener()相反。
注意:该方法只支持IE浏览器
定义一个函数,用来为指定元素绑定响应函数,解决兼容性问题。
/*
*addEventListener()中的this,是绑定事件的对象
* attachEvent()中的this,是window
* 需要统一两个方法的this
*/
//参数:1、obj 要绑定事件的对象 2、eventStr 事件字符串(不要on) 3、callback 回调函数
function bind(obj,eventStr,callback) {
if(obj.addEventListener){
obj.addEventListener(eventStr,callback,false);
}else {
obj.attachEvent("on"+eventStr,function () {
//在匿名函数中调用回调函数,这样就可以指定this
callback.call(obj);
});
}
};
//调用
bind(btn,"click",function () {
alert(1);
})
事件的传播
微软公司认为,认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行。
网景公司认为,认为事件应该是由外向内传播,也就是当事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后再向内传播给后代元素,也就是说事件应该在捕获阶段执行。
W3C综合了两个公司的方案,将事件的传播分成了三个阶段。
1、捕获阶段,在捕获阶段时从最外层的祖先元素,向目标元素事件的捕获,但是默认情况下此时不会触发事件。
2、目标阶段,事件捕获到目标元素,捕获结束开始在目标元素上触发事件。
3、冒泡阶段,事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件。
注意:
1、如果希望在捕获阶段就触发事件,可以将addEventListener的第三个参数设置为true,但是一般不用。
2、IE8及以下的浏览器没有捕获阶段。
拖拽事件练习
当我们拖拽网页中的内容时,浏览器会默认搜索引擎中搜索内容,此时会导致拖拽功能异常,这个是浏览器提供的默认行为,如果不希望发生,则可以通过在onmousedown后添加return false来取消默认行为,但是对IE8不起作用。当调用一个元素的setCapture()
方法以后,这个元素将会把下一次所有的鼠标按下相关的事件捕获到自身上。
注意:该方法只有IE支持,但在火狐中不会报错,而如果使用Chrome调用,会报错,所以需要做出判断。
//以下为在IE8的添加的内容
/*
*当调用一个元素的`setCapture()`方法以后,这个元素将会把下一次所有的鼠标按下相关的事件捕获到自身上。
*/
//设置box1绑定一个鼠标按下事件
box1.setCapture();
//以下为在IE8中的内容
//当鼠标松开时,取消对事件的捕获
box1.releaseCapture();
拖拽box1
window.onload = function () {
/*
拖拽box1元素流程:
1、当鼠标在被拖拽元素上按下时,开始拖拽onmousedown
2、当鼠标移动时被拖拽元素跟随鼠标移动onmousemove
3、当鼠标松开时,被拖拽元素被固定在该位置onmouseup
*/
//获取box1
var box1 = document.getElementById("box1");
//为box1绑定鼠标按下事件
//当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown
box1.onmousedown = function (event) {
/*
*当调用一个元素的`setCapture()`方法以后,这个元素将会把下一次所有的鼠标按下相关的事件捕获到自身上。
*/
//设置box1绑定一个鼠标按下事件
if(box1.setCapture){
box1.setCapture();
}
//求出div的偏移量 鼠标.clientX - 元素.offsetLeft
//求出div的偏移量 鼠标.clientY - 元素.offsetTop
//在按下就确定位置
event = event||window.event;
var ol = event.clientX - box1.offsetLeft;
var ot = event.clientY - box1.offsetTop;
//为document绑定一个onmousemove事件
document.onmousemove = function (event) {
event = event||window.event;
//当鼠标移动时被拖拽元素跟随鼠标移动onmousemove
//获取鼠标坐标
var left = event.clientX -ol;
var top = event.clientY -ot;
//修改box1的位置
box1.style.left = left+"px";
box1.style.top = top+"px";
}
//为元素绑定一个鼠标松开事件
document.onmouseup = function () {
//当鼠标松开时,被拖拽元素被固定在该位置onmouseup
//取消document的onmousemove事件
document.onmousemove = null;
//松开之后onmouseup还没停止,所以应该取消
document.onmouseup =null;
//当鼠标松开时,取消对事件的捕获
if (box1.releaseCapture){
box1.releaseCapture();
}
}
/*
* 当我们拖拽网页中的内容时,浏览器会默认搜索引擎中搜索内容,
* 此时会导致拖拽功能异常,这个是浏览器提供的默认行为,
* 如果不希望发生,则可以通过在onmousedown后添加return false来取消默认行为
* 但是对IE8不起作用
*/
return false;
}
//想要box2页可以拖拽,可以尝试写一个函数
}
拖拽函数
先获取想要拖拽的元素,然后将元素作为实参传递给这个函数再调用即可。
<script>
window.onload = function () {
var box1 = document.getElementById("box1");
var box2 = document.getElementById("box2");
drag(box1);
drag(box2);
};
function drag(obj){
obj.onmousedown = function (event) {
if(obj.setCapture){
obj.setCapture();
}
event = event||window.event;
var ol = event.clientX - obj.offsetLeft;
var ot = event.clientY - obj.offsetTop;
document.onmousemove = function (event) {
event = event||window.event;
var left = event.clientX -ol;
var top = event.clientY -ot;
obj.style.left = left+"px";
obj.style.top = top+"px";
}
document.onmouseup = function () {
document.onmousemove = null;
document.onmouseup =null;
if (obj.releaseCapture){
obj.releaseCapture();
}
};
return false;
};
}
</script>
滚轮的事件
onmousewheel鼠标滚轮滚动时触发,但是火狐不支持,火狐中使用DOMMouseScroll来绑定滚动事件,该事件需要通过addEventListener()函数来实现。
event.wheelDelta获取滚轮滚动方向,向上为正值,向下为负值,但是火狐不支持,火狐中使用event.detail获取滚轮滚动方向,向上为负值,向下为正值。
实现当鼠标滚轮向下滚动时,box1变长,当滚轮向上滚动时,box1变短。
window.onload = function () {
/*当鼠标滚轮向下滚动时,box1变长,当滚轮向上滚动时,box1变短*/
var box1 = document.getElementById("box1");
//为box1绑定一个鼠标滚轮滚动的事件
box1.onmousewheel = function (event) {
//火狐不支持onmousewheel,火狐中使用DOMMouseScroll来绑定滚动事件,
// 该事件需要通过addEventListener()函数来实现
event = event || window.event;
//判断滚轮滚动方向
//event.wheelDelta可以获取鼠标滚轮滚动的方向
//向上150,向下-150,不看大小只看正负
if(event.wheelDelta>0||event.detail<0){
box1.style.height = box1.clientHeight -20+"px";
}else {
box1.style.height = box1.clientHeight +20+"px";
}
//wheelDelta火狐不支持,火狐中使用event.detail,向上-3,向下3
//当鼠标滚轮向下滚动时,box1变长
//当滚轮向上滚动时,box1变短
event.preventDefault && event.preventDefault();
//在火狐中取消默认行为,但是IE8不支持,所以要做判断
return false;//取消默认行为
}
bind(box1,"DOMMouseScroll",box1.onmousewheel);
}
function bind(obj,eventStr,callback) {
if(obj.addEventListener){
obj.addEventListener(eventStr,callback,false);
}else {
obj.attachEvent("on"+eventStr,function () {
//在匿名函数中调用回调函数,这样就可以指定this
callback.call(obj);
});
}
};
键盘的事件
键盘事件一般都会绑定给一些可以获取到焦点的对象,或者是document。
onkeydown 按键被按下,对于onkeydown来说如果一直按着某个按键不松手,则事件会一直触发;当onkeyup连续触发时,第一次和第二次之间会间隔长一点,其他的会非常快。这种设计是为了防止人误操作。
onkeyup 按键被松开。
keyCode 获取按键的编码,可以判断哪个按键被按下。
altKey、ctrlKey、shiftKey 这三个用来判断alt ctrl 和 shift 是否被按下,如果按下则返回true,否则返回false。
event.keyCode === 89 && event.ctrlKey//判断是不是同时按下ctrl和y健
在文本框中输入内容属于onkeydown的默认行为,如果在onkeydown中取消了默认行为,则输入的内容不会出现在文本框中。
使文本框中不能有数字
window.onload = function () {
var inp = document.getElementsByTagName("input")[0];
inp.onkeydown = function(event){
event = event||window.event;
//数字编码 48-57
if(event.keyCode>=48 && event.keyCode<=57){
return false;
}
};
};
结合定时器使div根据不同的方向键不同的方向移动
window.onload = function () {
//速度由定时器控制,方向由键盘控制
var speed = 20;
var dir = 0;
setInterval(function () {
switch (dir) {
case 37:
box1.style.left=box1.offsetLeft-speed+"px"
break;
case 38:
box1.style.top=box1.offsetTop-speed+"px"
break;
case 39:
box1.style.left=box1.offsetLeft+speed+"px"
break;
case 40:
box1.style.top=box1.offsetTop+speed+"px"
break;
}
},30)
//给document绑定键盘事件
document.onkeydown = function (event) {
event = event || window.event;
//左、上、右、下 37、38、39、40
//当用户按了ctrl以后,速度加快
if (event.ctrlKey) {
speed = 50;
}else {
speed=10;
}
dir = event.keyCode;
};
//当按键松开时,div不再移动
document.onkeyup = function () {
dir = 0;
}
}