事件基础
来源:互联网 发布:sql怎么设置 identity 编辑:程序博客网 时间:2024/06/08 16:35
1.什么是事件
2.事件对象及兼容处理
3.事件的传播机制
4.案例-鼠标跟随jQuery
5.案例-鼠标跟随JS版
6.鼠标跟随、深入理解事件的传播机制
7.事件委托/事件代理
8.案例-京东商城放大镜
9.案例-百度搜索框
10.案例-多级菜单JS版
11.案例-多级菜单jQuery版
12.拖拽demo实现基本的效果
13.拖拽demo解决鼠标丢失
事件分为两部分:
1.行为本身:浏览器天生就赋予其的行为。onclick、onmouseover(onmouserenter)、onmouseout(onmouseleave)、onmousemove、ommousemove、onmousedown、onmouseup、onmousewheel(鼠标滚轮滚动行为)、onscroll(滚动条滚动行为)、onresize(window.onresize 浏览器窗口大小改变事件)、onload、onunload、onfouse文本框获取焦点行为)、onblur(浏览器失去焦点)、onkeydown(键盘按下行为)、onkeyup……
哪怕没有给上述行为绑定方法,事件也存在。当点击这个盒子的时候,同样会触发它的onclick行为,只是什么事情都没做而已。
2.事件绑定:给元素的某一个行为绑定一个方法
//DOM0级事件绑定var oDiv = document.getElementById("div1");oDiv.onclick = function () { //当触发oDiv的onclick行为的时候,会把绑定的这个函数执行};
//DOM2级事件绑定oDiv.addEventListener("click", function () { console.log("ok");}, false);
onclick这个行为定义在当前元素的私有属性上;
addEventListener这个属性是定义在当前元素所属EventTarget这个类的原型上的
oDiv.onclick = function () {};
把匿名函数定义的部分当做一个值赋值给oDiv的点击行为(函数表达式)
当触发div的点击行为的时候,会执行对应绑定上的方法
不仅仅把绑定的方法执行了,而且浏览器还默认的给这个方法传递了一个参数值:MouseEvent:鼠标事件对象。
- MouseEvent是一个对象数据类型值,里面包含了很多的属性名和属性值,这些都是用来记录当前鼠标的相关信息的
- MouseEvent -> UIEvent -> Event -> Object
- MouseEvent记录的是页面中唯一一个鼠标每一次触发时候的相关信息,和到底是在哪个元素上触发的没有关系
关于事件对象(MouseEvent)的兼容性问题:
1、事件对象本身的获取存在兼容问题:标准浏览器中是浏览器给方法传递的参数,只需要定义形参e就可以获取到
oDiv.onclick = function (e) { console.log(e);};
2、在IE6-8中,浏览器不会给方法传递参数,如果需要的话,需要到window.event中获取查找。
解决方法:
oDiv.onclick = function (e) { e = e || window.event; console.log(e);};
常用信息:
- e.clientX/e.clientY:鼠标触发点距离当前屏幕左上角的坐标值
- e.type:存储的是当前鼠标触发的行为类型,如“click”
- e.target:事件源,当前鼠标触发的是哪个元素,那么它存储的就是哪个元素。存在兼容性问题,在IE6-8中不存在这个属性,即为undefined,可以使用e.srcElement来获取事件源。解决方法:
e.target = e.target || e.srcElement;
- e.preventDefault:阻止浏览器的默认行为。如a标签的默认行为就是跳转页面,但是有时候使用a标签,只是想应用它的特殊性,并不想点击的时候跳转。存在兼容性问题,在IE6-8中不存在这个属性,需要使用e.returnValue = false;来代替。
a.onclick = function (e) { e = e || window.event; e.preventDefault ? e.preventDefault() : e.returnValue = false; //或者:return false; //或者:见下};
<li><a href="javascript:;"></a></li>/*直接在HTML结构上阻止或者:href="javascript:void 0;"href="javascript:void 1;"*/
- e.pageX/e.pageY:当前鼠标触发点距离body左上角(页面第一屏幕最左上角)的x/y轴的坐标。存在兼容性问题,在IE6-8中不存在这个属性,即为undefined,解决方法:
e.pageX = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));e.pageY = e.pageY || (e.clientY + (document.documentElement.scrollTop || document.body.scrollTop));
- e.stopPropagation:阻止事件的冒泡传播,在IE6-8中不存在这个属性,解决方法如下:
e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
- e.keycode:当前键盘上每一个键对应的值,如:空格:32;回退键:8;回车键:13;delete:46;左:37;上:38;右:39;下:40
有以下代码:
<body><div id="outer"> <div id="inner"> <div id="center"></div> </div></div><script type="text/javascript"> var outer = document.getElementById("outer"), inner = document.getElementById("inner"), center = document.getElementById("center"); document.body.onclick = function () { console.log("body"); }; outer.onclick = function () { console.log("outer"); }; inner.onclick = function () { console.log("inner"); }; center.onclick = function () { console.log("center"); };</script></body>
点击时,控制台会输出:center、inner、outer、body,这就涉及到了事件的默认传播机制。
事件的默认传播机制分为三个阶段:
- 捕获阶段:从外向里依次查找元素
- 目标阶段:当前事件源本身的操作
- 冒泡阶段:从内到外依次触发相关的行为
最常用的就是冒泡阶段。
用DOM0级事件绑定给元素的某一个行为绑定的方法,都是在行为触发后的冒泡阶段把方法执行的。如图:
冒泡阶段:
- 当前center的click行为被触发,如果给其绑定了方法,首先把center对应的方法执行(目标阶段)
- 不仅仅center的click行为被触发了,它所有的父级元素的click行为也会被触发。inner的click行为触发->如果给inner也绑定了方法,inner对应的方法也会执行
- 同理依次查找outer、body、html、document
注意:每个浏览器传播到的最顶层是不一样的。谷歌中可以到document,IE中只能传播到HTML。
document.body.addEventListener("click", function () { console.log("body");}, false); //第一个参数是行为的类型,第二个参数是给当前的行为绑定的方法,第三个参数是控制在哪个阶段发生,true是捕获阶段发生,false是冒泡阶段发生outer.addEventListener("click", function () { console.log("outer");}, true);inner.addEventListener("click", function () { console.log("inner");}, false);
点击center的div,输出:outer、inner、body
4.案例-鼠标跟随jQuery效果图:
HTML代码:
<div id="box" class="box"> <img src="img/1.jpg" bigImg="img/11.jpg"/> <img src="img/2.jpg" bigImg="img/22.jpg"/> <img src="img/3.jpg" bigImg="img/33.jpg"/> <img src="img/4.jpg" bigImg="img/44.jpg"/> <div id="mark"> <img src="img/11.jpg"/> </div></div>
CSS代码:
body, div, ing { margin: 0; padding: 0;}img { display: block; border: none;}.box { width: 450px; margin: 20px auto; position: relative;}.box img { width: 100px; border: 1px solid #777777; float: left; margin-left: 10px;}#mark { position: absolute; top: 0px; left: 0; width: 384px; height: 216px; border: 1px solid #5bc0de; z-index: 10; display: none;}#mark img { border: none; float: none; margin-left: 0px; width: 100%; height: 100%;}
JavaScript代码(jQuery):
$(function () { var $box = $("#box"), $mark = $("#mark"), $boxOffset = $box.offset(); //获取当前元素距离body的偏移 $box.children("img").mouseover(function (e) { e = e || window.event; e.target = e.target || e.srcElement; var left = e.clientX - $boxOffset.left + 10; var top = e.clientY - $boxOffset.top + 10; $mark.stop().show(100).css({left: left, top: top}).find("img").attr("src", e.target.getAttribute("bigImg")); }).bind("mousemove", function (e) { e = e || window.event; e.target = e.target || e.srcElement; var left = e.clientX - $boxOffset.left + 10; var top = e.clientY - $boxOffset.top + 10; $mark.css({left: left, top: top}); }).bind("mouseout", function (e) { $mark.stop().hide(100); });});
5.案例-鼠标跟随JS版效果图:
HTML代码:
<div id="box"> <!--<div id="mark"></div>--></div>
CSS代码:
body, div { margin: 0; padding: 0;}#box { position: relative; margin: 20px auto; width: 300px; height: 300px; background: #5bc0de;}#mark { position: absolute; top: 0; left: 0; width: 100px; height: 100px; background: #FFAAAA;}
JS代码:
var box = document.getElementById("box");box.onmouseover = function (e) { e = e || window.event; var mark = document.createElement("div"); mark.id = "mark"; this.appendChild(mark); mark.style.left = e.clientX - this.offsetLeft + 5 + "px"; mark.style.top = e.clientY - this.offsetTop + 5 + "px";};box.onmousemove = function (e) { e = e || window.event; var mark = document.getElementById("mark"); if (mark) { mark.style.left = e.clientX - this.offsetLeft + 5 + "px"; mark.style.top = e.clientY - this.offsetTop + 5 + "px"; }};
以上代码会出现一个问题:当鼠标移动过快的时候会进入到mark盒子,触发到它的mouseover行为,由于事件的冒泡传播机制,导致box的mouseover会重新触发,导致盒子一直被触发
解决方法:阻止mark盒子的onmouseover行为的冒泡传播
如果增加onmouseout事件,依然有问题,鼠标快速移动,首先会到mark上,此时浏览器在计算mark的位置,计算完成,mark到达指定的位置,此时鼠标又重新回到box上,触发了box的mouseover,也触发了mark的mouseout,mark的mouseout被触发,也会传播到box的mouseout上,会把mark先删除,然后再创建……
box.onmouseout = function (e) { e = e || window.event; var mark = document.getElementById("mark"); if (mark) { this.removeChild(mark); }};
onmouseenter和onmouseover的区别:
都是鼠标滑上去的行为,但是onmouseenter默认阻止了浏览器的冒泡传播,即:mark的mouseenter行为触发,不会传播到box。而onmouseover是存在冒泡传播的,想要阻止的话只能自己写代码阻止。
onmouseleave和onmouseout同理。
所以代码可以写成:
var box = document.getElementById("box");box.onmouseenter = function (e) { e = e || window.event; var mark = document.createElement("div"); mark.id = "mark"; this.appendChild(mark); mark.style.left = e.clientX - this.offsetLeft + 5 + "px"; mark.style.top = e.clientY - this.offsetTop + 5 + "px";};box.onmousemove = function (e) { e = e || window.event; var mark = document.getElementById("mark"); if (mark) { mark.style.left = e.clientX - this.offsetLeft + 5 + "px"; mark.style.top = e.clientY - this.offsetTop + 5 + "px"; }};box.onmouseleave = function (e) { e = e || window.event; var mark = document.getElementById("mark"); if (mark) { this.removeChild(mark); }};
6.鼠标跟随、深入理解事件的传播机制效果图:鼠标滑到粉盒子上时,蓝盒子出现,在蓝盒子上时,不消失。
代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> body, div { margin: 0; padding: 0; } #box { position: relative; width: 100px; height: 30px; background: #FFAAAA; } #mark { position: absolute; left: 0; top: 30px; width: 300px; height: 100px; background: #5bc0de; display: none; } </style></head><body><div id="box"> <div id="mark"></div></div><script type="text/javascript"> var box = document.getElementById("box"); var mark = document.getElementById("mark"); box.onmouseenter = function () { mark.style.display = "block"; }; box.onmouseleave = function () { mark.style.display = "none"; };</script></body></html>
7.事件委托、事件代理利用事件的冒泡传播机制,即触发当前元素的某个行为,它父级所有元素的相关行为都会被触发。利用这个机制,如果容器中有很多元素都需要绑定点击事件,没有必要一个个的绑定,只需要给最外层容器绑定一个点击事件即可,在这个方法执行的时候,通过事件源(e.target)的区分来进行不同的操作。
事件委托的简单应用效果图:
说明:
点击购物车,出现粉色框,点击粉色框不消失,点击购物车消失,点击空白处消失。
代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> body, div, span { margin: 0; padding: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; } html,body { width: 100%; height: 100%; overflow: hidden; } #box { position: relative; left: 50%; top: 50px; margin-left: -50px; width: 100px; height: 30px; border: 1px solid #9783b9; line-height: 30px; text-align: center; cursor: pointer; } #mark { position: absolute; top: 30px; left: -1px; width: 300px; height: 100px; line-height: 100px; text-align: center; background: #FFAAAA; border: 1px solid #9783b9; } </style></head><body><div id="box"> <span>购物车</span> <div id="mark" style="display: none">查看购物车的详细信息</div></div><script type="text/javascript"> var mark = document.getElementById("mark"); document.body.onclick = function (e) { console.log("111"); e = e || window.event; e.target = e.target || e.srcElement; //如果点击的是box或者#box下的span,判断mark是否显示,显示就隐藏,反之显示 if (e.target.id === "box" || (e.target.tagName.toLowerCase() === "span" && e.target.parentNode.id === "box")) { if (mark.style.display === "none") { mark.style.display = "block"; } else { mark.style.display = "none"; } return; } //如果事件源是#mark,不进行任何操作 if (e.target.id === "mark") { return; } //以上都不是,直接让#mark隐藏 mark.style.display = "none"; };</script></body></html>
8.案例-京东商城放大镜效果图:
代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> body, div, img { margin: 0; padding: 0; } img { display: block; border: none; } #box { position: absolute; top: 20px; left: 20px; width: 350px; height: 350px; border: 1px; box-shadow: 3px 3px 10px 0 #111; } #box img { width: 350px; height: 350px; } #mark { position: absolute; top: 0; left: 0; width: 175px; height: 175px; background: #000; opacity: 0.5; filter: alpha(opacity=50); cursor: move; display: none; } #boxRight { display: none; position: absolute; width: 350px; height: 350px; top: 20px; left: 440px; overflow: hidden; } /*右侧图片大小是左边2倍*/ #boxRight img { position: absolute; width: 700px; height: 700px; top: 0; left: 0; } </style></head><body><div id="box"> <img src="img/jd.jpg"/> <div id="mark"></div></div><div id="boxRight"> <img src="img/jd.jpg"/></div><script type="text/javascript"> //放大镜原理: //mark横向是box的一半,纵向也是box的一半,那么右侧大图的横向和纵向应该是左边小图的二倍 var box = document.getElementById("box"), mark = document.getElementById("mark"), boxRight = document.getElementById("boxRight"); //设置mark盒子的位子信息 function setPosition(e) { //正常情况下获取的top/left,但是需要做边界判断 var top = e.clientY - box.offsetTop - (mark.offsetHeight / 2); var left = e.clientX - box.offsetLeft - (mark.offsetWidth / 2); //边界判断: var tempL = 0, tempT = 0; var minL = 0, minT = 0, maxL = box.offsetWidth - mark.offsetWidth, maxT = box.offsetHeight - mark.offsetHeight; if (left < minL) { mark.style.left = minL + "px"; tempL = minL; } else if (left > maxL) { mark.style.left = maxL + "px"; tempL = maxL; } else { mark.style.left = left + "px"; tempL = left; } if (top < minT) { mark.style.top = minT + "px"; tempT = minT; } else if (top > maxT) { mark.style.top = maxT + "px"; tempT = maxT; } else { mark.style.top = top + "px"; tempT = top; } //让右侧的图片跟着运动 var oImg = boxRight.getElementsByTagName("img")[0]; oImg.style.left = -tempL * 2 + "px"; oImg.style.top = -tempT * 2 + "px"; } box.onmouseenter = function (e) { e = e || window.event; mark.style.display = "block"; setPosition(e); boxRight.style.display = "block"; }; box.onmousemove = function (e) { e = e || window.event; setPosition(e); }; box.onmouseleave = function (e) { e = e || window.event; mark.style.display = "none"; boxRight.style.display = "none"; };</script></body></html>
9.案例-百度搜索框效果图:
分析:
显示时情况:
- 文本框获取焦点,并且文本框中有内容的时候
- 在文本框中输入或者删除内容时,如果内容没有清空就显示,否则就隐藏
隐藏时情况:
- 点击页面中其余的位置(除文本框和searchList里面的每一行),都隐藏
- 点击searchList中的列表隐藏,但是还要把列表中的内容放到文本框中
代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> body, div,input, ul, li { margin: 0; padding: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; } input { display: block; outline: none; /*清除彩色边框*/ } a { display: block; text-decoration: none; color: #000; } a:hover, a:active, a:target { text-decoration: none; color: #000; } ul, li { list-style: none; } .box { width: 500px; position: absolute; top: 20px; left: 50%; margin-left: -250px; } .box input { width: 300px; height: 35px; padding: 0 10px; border: 1px solid #888; } .box ul { display: none; border: 1px solid #888; position: relative; top: -1px; } .box ul li, .box ul a { height: 30px; line-height: 35px; } .box ul a { padding: 0 10px; } .box ul a:hover { background: #eee; } </style></head><body><div class="box"> <input type="text" id="searchInp"/> <ul id="searchList"> <li><a href="javascript:;">冰箱</a></li> <li><a href="javascript:;">彩电</a></li> <li><a href="javascript:;">洗衣机</a></li> <li><a href="javascript:;">废品</a></li> <li><a href="javascript:;">废塑料</a></li> </ul></div><script type="text/javascript"> var searchInp = document.getElementById("searchInp"), searchList = document.getElementById("searchList"); //不管是获取焦点还是在里面编辑内容,都是有内容显示,没内容隐藏 searchInp.onfocus = searchInp.onkeyup = function () { var val = this.value.replace(/(^ +| +$)/g, ""); //获取文本框中的内容,并且去除它的首尾空格 searchList.style.display = val.length > 0 ? "block" : "none"; }; document.body.onclick = function (e) { e = e || window.event; e.target = e.target || e.srcElement; //如果点击的事件源是searchList下的a标签,让searchList隐藏,并且把当前点击的内容放到文本框中 if (e.target.tagName.toLowerCase() === "a" && e.target.parentNode.parentNode.id === "searchList") { searchList.style.display = "none"; searchInp.value = e.target.innerHTML; return; } //如果事件源是文本框还需要单独处理// if(e.target.id==="searchInp"){// return;// } searchList.style.display = "none"; }; //可以阻止一个容器中某些特殊性的元素,让其不在委托的范围内,只需要把这些不需要委托的事件阻止即可 searchInp.onclick = function (e) { e = e || window.event; e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true; };</script></body></html>
10.案例-多级菜单JS版效果图:
完整代码如下:
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 14px; } ul, li { list-style: none; } .box { width: 300px; margin: 10px; padding: 10px; border: 1px dashed #5bc0de; /*渐进增强:首先设置一个纯色的背景,对于不兼容css3的浏览器来说会使用纯色,对于兼容的浏览器来说,下面再额外的增加一些渐变色,这样的话会把纯色的覆盖掉*/ background: #FFAAAA; background: -webkit-linear-gradient(top left, #5bc0de, #bce8f1); } .box li { position: relative; line-height: 30px; } .box em { position: absolute; width: 16px; height: 16px; background: #777777; top: 7px; left: 0; cursor: pointer; } .box em.open { background: #333; } .box span { display: block; padding-left: 20px; } .box .two { margin-left: 20px; } .box .three { margin-left: 40px; } .box .four { margin-left: 60px; } .box .two, .box .three, .box .four { display: none; } </style></head><body><div class="box" id="box"> <ul> <li> <em></em><span>第一级第一个</span> <ul class="two"> <li><span>第二级第一个</span></li> <li> <em></em><span>第二级第二个</span> <ul class="three"> <li><span>第三级第一个</span></li> <li><span>第三级第二个</span></li> <li> <em></em><span>第三级第三个</span> <ul class="four"> <li><span>第四级第一个</span></li> <li><span>第四级第二个</span></li> <li><span>第四级第三个</span></li> </ul> </li> </ul> </li> <li> <em></em><span>第二级第三个</span> <ul class="three"> <li><span>第三级第一个</span></li> <li><span>第三级第二个</span></li> <li><span>第三级第三个</span></li> </ul> </li> </ul> </li> <li> <em></em><span>第一级第二个</span> <ul class="two"> <li><span>第二级第一个</span></li> <li> <em></em><span>第二级第二个</span> <ul class="three"> <li><span>第三级第一个</span></li> <li><span>第三级第二个</span></li> <li> <em></em><span>第三级第三个</span> <ul class="four"> <li><span>第四级第一个</span></li> <li><span>第四级第二个</span></li> <li><span>第四级第三个</span></li> </ul> </li> </ul> </li> <li> <em></em><span>第二级第三个</span> <ul class="three"> <li><span>第三级第一个</span></li> <li><span>第三级第二个</span></li> <li><span>第三级第三个</span></li> </ul> </li> </ul> </li> </ul></div><script type="text/javascript" src="utils.js"></script><script type="text/javascript"> var box = document.getElementById("box"); //把列表中的span(前面带em的)设置一个cursor: pointer;的样式 var spanList = box.getElementsByTagName("span"); for (var i = 0; i < spanList.length; i++) { var curSpan = spanList[i]; var curPre = utils.prev(curSpan); //获取当前span的上一个哥哥元素节点 if (curPre && curPre.tagName.toLowerCase() === "em") { curSpan.style.cursor = "pointer"; } } //使用事件委托实现操作 box.onclick = function (e) { e = e || window.event; var tar = e.target || e.srcElement; //只有点击的是em/span标签才进行展开或者收缩的操作 if (/^(em|span)$/i.test(tar.tagName)) { var parent = tar.parentNode; //获取父亲 var oEm = utils.children(parent, "em")[0]; var firstUl = utils.children(parent, "ul")[0];//获取父亲子集中第一个ul if (firstUl) { //只有存在才进行相关的操作 //这个ul当前是隐藏让其显示,否则隐藏 var isBlock = utils.css(firstUl, "display") === "block" ? true : false; if (isBlock) { //当前是显示的 firstUl.style.display = "none"; oEm ? utils.removeClass(oEm, "open") : null; //当外层的收起,里层所有的ul都隐藏,并且所有的em都要移除open样式 var allUl = parent.getElementsByTagName("ul"), allEm = parent.getElementsByTagName("em"); for (var i = 0; i < allEm.length; i++) { allUl[i].style.display = "none"; utils.removeClass(allEm[i], "open"); } } else { //当前是隐藏的 firstUl.style.display = "block"; oEm ? utils.addClass(oEm, "open") : null; } } } };</script></body></html>
utils.js见:http://blog.csdn.net/ruirui_1996/article/details/78116836
11.案例-多级菜单jQuery版var $box = $("#box");$box.find("span").each(function () { //$(this) 每一次循环当前循环的这个元素 var $pre = $(this).prev(); if ($pre[0] && $pre[0].tagName.toLowerCase() === "em") { $(this).css("cursor", "pointer"); }});function fn() { var $par = $(this).parent(); var $ul = $($par.children("ul")[0]); var $em = $($par.children("em")[0]); if ($ul.length > 0) { var isBlock = $ul.css("display") === "block" ? true : false; $ul.slideToggle(); $em.toggleClass("open"); //当前如果是收缩,需要把子子孙孙中所有的ul/em都隐藏和移除open样式 if (isBlock) { $par.find("ul").css("display", "none"); $par.find("em").removeClass("open"); } }}$box.delegate("em", "click", fn); //给$box绑定点击事件,如果当前的事件源是em的话执行fn$box.delegate("span", "click", fn);
12.拖拽demo实现基本的效果原理:
当鼠标在盒子上按下的时候开始拖拽(给盒子绑定onmousemove和onmouseup)。当鼠标移动的时候,计算盒子的最新位置,当鼠标抬起的时候,拖拽已经结束了,move和up就没用了,再把move和up移除。
开始记录一下鼠标的开始位置strX/strY和盒子的开始位置strListrT。
当鼠标移动的过程中,获取最新的鼠标位置,用现有的位置减起始位置等于鼠标移动的距离A
当前盒子的位置=盒子的起始位置+鼠标移动的距离A
<!DOCTYPE html><html><head> <meta charset="UTF-8"> <title>Title</title> <style type="text/css"> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; } #box { position: absolute; /*top: 50%;*/ /*left:50%;*/ /*margin: -100px 0 0 -100px;*/ /*或者:*/ /*position: absolute;*/ /*top: 0;*/ /*left: 0;*/ /*right: 0;*/ /*bottom: 0;*/ /*margin: auto;*/ /*IE下兼容不好 主要用于移动端的开发*/ width: 200px; height: 200px; background: #5bc0de; cursor: move; } </style></head><body><div id="box"></div><script type="text/javascript"> var box = document.getElementById("box"); box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight) - box.offsetHeight) / 2 + "px"; box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth) - box.offsetWidth) / 2 + "px"; box.onmousedown = down; function down(e) { e = e || window.event; //记录开始位置的信息 this["strX"] = e.clientX; this["strY"] = e.clientY; this["strL"] = parseFloat(this.style.left); this["strT"] = parseFloat(this.style.top); //给元素绑定移动和抬起的事件 this.onmousemove = move; this.onmouseup = up; } function move(e) { e = e || window.event; var curL = e.clientX - this["strX"] + this["strL"]; var curT = e.clientY - this["strY"] + this["strT"]; console.lo //边界判断 var minL = 0, minT = 0, maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth, maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight; curL = curL < minL ? minL : (curL > maxL ? maxL : curL); curT = curT < minT ? minT : (curT > maxT ? maxT : curT); this.style.left = curL + "px"; this.style.top = curT + "px"; } function up(e) { this.onmousemove = null; this.onmouseup = null; }</script></body></html>
13.拖拽demo解决鼠标丢失鼠标焦点丢失:
当鼠标移动过快的时候,鼠标会脱离盒子,导致盒子的mouseup和mousemove事件都移除不掉。
在IE和火狐中,可以使用setCapture()方法将鼠标和盒子绑在一起,用releaseCapture()解绑,但是在谷歌下不兼容。
谷歌下解决方法:
鼠标始终在文档中,把mousemove和mouseup绑定给document
优化后JS代码:
<script type="text/javascript"> var box = document.getElementById("box"); box.style.top = ((document.documentElement.clientHeight || document.body.clientHeight) - box.offsetHeight) / 2 + "px"; box.style.left = ((document.documentElement.clientWidth || document.body.clientWidth) - box.offsetWidth) / 2 + "px"; box.onmousedown = down; function down(e) { e = e || window.event; //记录开始位置的信息 this["strX"] = e.clientX; this["strY"] = e.clientY; this["strL"] = parseFloat(this.style.left); this["strT"] = parseFloat(this.style.top); //给元素绑定移动和抬起的事件 if (this.setCapture) { //把当前鼠标和this绑定在一起 this.setCapture(); this.onmousemove = move; this.onmouseup = up; } else { var _this = this; //_this是#box document.onmousemove = function (e) { // move(e); //move中的方法为window move.call(_this,e); }; document.onmouseup = function (e) { up.call(_this,e); }; } } function move(e) { e = e || window.event; var curL = e.clientX - this["strX"] + this["strL"]; var curT = e.clientY - this["strY"] + this["strT"]; //边界判断 var minL = 0, minT = 0, maxL = (document.documentElement.clientWidth || document.body.clientWidth) - this.offsetWidth, maxT = (document.documentElement.clientHeight || document.body.clientHeight) - this.offsetHeight; curL = curL < minL ? minL : (curL > maxL ? maxL : curL); curT = curT < minT ? minT : (curT > maxT ? maxT : curT); this.style.left = curL + "px"; this.style.top = curT + "px"; } function up(e) { if (this.releaseCapture) {//把当前的鼠标和this解绑 this.releaseCapture(); this.onmousemove = null; this.onmouseup = null; } else { document.onmousemove = null; document.onmouseup = null; } }</script>
- 事件基础
- 事件基础
- 基础事件
- 事件基础
- jQuery基础事件-绑定事件
- jQuery基础事件-事件简写
- js基础 事件基础一
- js基础 事件基础二
- WSS3SDK之:事件基础
- 鼠标按键事件基础
- 基础_C# 事件
- 【c#基础6】事件
- jquery基础三 事件
- JS之事件基础
- JQuery 基础事件
- jQuery Mobile 基础事件
- 8.jQuery 基础事件
- javaScript基础 - 事件
- 共享单车引发自行车行业战火再燃,巨头捷安特与行业NO1 LIVALL联手出击?
- 大获成功!SpaceX第二次发射并回收重复利用火箭
- 极智嘉(Geek+)CEO郑勇:智能物流和仓储改变商业未来 | CCF-GAIR 2017
- GlobalFoundries公布7nm工艺细节:最大芯片尺寸700mm²,2018年量产
- python里使用正则表达式的选项参数
- 事件基础
- shell脚本报错:"[: =: unary operator expected"
- 自我介绍
- java小项目之用户信息添加
- 将大脑比作计算机,正在阻碍脑科学研究
- IntelliJ IDEA Kotlin第一步从hello world开始
- RadioButton+RadioGroup
- 数据结构学习记录-链式栈
- 深度好贴,mark一下!