js鼠标悬浮水平弹性伸缩的导航菜单
本章节分享一段代码实例,它实现了鼠标悬浮导航水平伸缩的功能。
下面就给出代码,并进行详细的分析,代码实例如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="author" content="http://www.pipipi.net/" /> <title>前端教程网</title> <style> *{ margin:0px; padding:0px; } body{ background:#fff; } .naver{ list-style-type:none; width:700px; overflow:hidden; margin:100px auto 0; } .naver li{ width:100px; height:50px; overflow:hidden; font-size:16px; text-align:center; cursor:pointer; } .naver li a,.naver li a:hover{ display: block; width:100px; height:50px; line-height:50px; color:#FFF; text-decoration:none; } .co1{background:#649e37} .co2{background:#028fbc} </style> <script type="text/javascript"> window.onload = function() { var oUl = document.getElementById("nav"); var aLi = oUl.getElementsByTagName("li"); var index = 0; for (index = 0; index < aLi.length; index++) { aLi[index].timer = null; aLi[index].speed = 0; aLi[index].onmouseover = function() { startMove(this, 250); }; aLi[index].onmouseout = function() { startMove2(this, 100); }; } }; function startMove(obj, iTarget) { if (obj.timer) { clearInterval(obj.timer); } obj.timer = setInterval(function() { doMove(obj, iTarget); }, 30) }; function doMove(obj, iTarget) { obj.speed += 3; if (Math.abs(iTarget - obj.offsetWidth) < 1 && Math.abs(obj.speed) < 1) { clearInterval(obj.timer); obj.timer = null; } else { if (obj.offsetWidth + obj.speed >= iTarget) { obj.speed *= -0.7; obj.style.width = iTarget + "px"; } else { obj.style.width = obj.offsetWidth + obj.speed + "px"; } } }; function startMove2(obj, iTarget) { if (obj.timer) { clearInterval(obj.timer); } obj.timer = setInterval(function() { doMove2(obj, iTarget); }, 30) }; function doMove2(obj, iTarget) { obj.speed -= 3; if (Math.abs(iTarget - obj.offsetWidth) < 1 && Math.abs(obj.speed) < 1) { clearInterval(obj.timer); obj.timer = null; } else { if (obj.offsetWidth + obj.speed <= iTarget) { obj.speed *= -0.7; obj.style.width = iTarget + "px"; } else { obj.style.width = obj.offsetWidth + obj.speed + "px"; } } }; </script> </head> <body> <ul id="nav" class="naver"> <li class="co1"><a href="#">前端教程网一</a></li> <li class="co2"><a href="#">前端教程网二</a></li> <li class="co1"><a href="#">前端教程网三</a></li> <li class="co2"><a href="#">前端教程网四</a></li> <li class="co1"><a href="#">前端教程网五</a></li> </ul> </body> </html>
上面的代码实现了我们的要求,下面介绍一下它的实现过程。
一.代码注释:
(1).window.onload = function() {},当文档内容完全加载完毕再去执行函数中的代码。
(2).var oUl = document.getElementById("nav"),获取id属性值为nav的元素对象。
(3).var aLi = oUl.getElementsByTagName("li"),获取oUl下的li元素集合。
(4).var index = 0,生命一个变量病赋初值为0,在for循环中使用。
(5).for (index = 0; index < aLi.length; index++){},遍历li元素集合中的每一个元素。
(6).aLi[index].timer = null,为当前的li元素对象添加一个timer属性并赋初值为null,用作定时器函数的标识。
(7).aLi[index].speed = 0,初始化元素的伸缩速度。
(8).aLi[index].onmouseover = function() {
startMove(this, 250);
},为当前li元素注册onmouseover事件处理函数。
当鼠标悬浮的时候就会执行此函数,然后调用startMove()函数,第一个参数this就是当前li元素,第二个参数是元素伸展的最大宽度。
(9).aLi[index].onmouseout = function() {
startMove2(this, 100);
}为当前li元素注册onmouseout事件处理函数。
当鼠标悬浮的时候就会执行此函数,然后调用startMove2()函数,第一个参数this就是当前li元素,第二个参数是元素收缩的最小宽度。
(10).function startMove(obj, iTarget) {
if (obj.timer) {
clearInterval(obj.timer);
}
obj.timer = setInterval(function() {
doMove(obj, iTarget);
}, 30)
},此函数实现了li元素的伸展或者收缩效果,第一个参数是一个元素对象,第二个参数是目标尺寸。
首先判断当前有定时器函数的执行,如果有,那么就停止当前定时器函数的执行,否则就会出现多个定时器函数重叠执行的情况。
最后,开始一个新的定时器函数的执行。
(11).function doMove(obj, iTarget) {},此方法实现了具有弹性效果的伸展运动,第一个参数是元素对象,第二个参数是目标值。
(12).obj.speed += 3,每一次执行,速度值就会加3。
(13).if (Math.abs( iTarget - obj.offsetWidth)< 1 && Math.abs(obj.speed) < 1) {
clearInterval(obj.timer);
obj.timer = null;
},如果当前的目标值减去元素当前的宽度值小于1,并且速度的值小于1
那么就停止定时器函数的执行,也就是伸展任务完成。
(14).else {
if (obj.offsetWidth + obj.speed >= iTarget) {
obj.speed *= -0.7;
obj.style.width = iTarget + "px";
}
else {
obj.style.width = obj.offsetWidth + obj.speed + "px";
}
},如果不满足上一步骤的条件,那么进行如下判断:
如果当前宽度加上当前速度大于目标宽度的话,就将速度转换为负数,并乘以0.7(不能直接乘以-1,否则的话li元素宽度又会回到原来的尺寸).最后将元素的宽度直接设置为目标尺寸。
如果上面的条件也不满足的话,就在原来宽度基础上加上当前的速度,由于速度是累积的,所以速度会越来越快。
第13和14步实现了弹性效果,虽然代码介绍完毕,不少朋友可能还没有明白会什么会有弹性效果,下面做一下说明:
当开始运动的时候,元素宽度会越来越快的进行伸展。
到达一个临界点(当前的宽度加上当前速度要大于等于目标尺寸)之后,元素宽度里面设置为目标宽度,这时候速度也变成了负数,但是由于是乘以-0.7,所以元素的宽度在弹性变化的时候就不能够收缩到最初的尺寸,于是当元素再次伸展到目标尺寸的时候,速度就比上一次要小,因为执行obj.speed += 3的次数少了。如此往复(往复也就实现了弹性效果)最终会满足13部的判断条件。
二.相关阅读:
(1).getElementsByTagName()可以参阅document.getElementsByTagName()一章节。
(2).onmouseover事件可以参阅javascript mouseover事件一章节。
(3).onmouseout事件可以参阅javascript mouseout事件一章节。
(4).setInterval()可以参阅setInterval()一章节。
(5).Math.abs()可以参阅javascript Math.abs()一章节。
(6).offsetWidth可以参阅js offsetWidth一章节。