原⽣JS实现导航下拉菜单效果
这个导航下拉菜单需要实现的功能是:下拉菜单的宽度与浏览器视⼝的宽度⼀样宽;⼀级导航只有两项,当⿏标移到⼀级导航上的导航项时,相应的⼆级导航出现。在本案例中通过改变⼆级导航的⾼度来实现⼆级导航的显⽰和消失。为了便于理解我画了⼀个图,如下:
在这个案例主要⽤到的知识有:设置定时器,清除定时器,mouseout和mouseover事件,另外还有css中position相关知识。本案例分为两部分讲解。第⼀部分html和css,第⼆部分js。
⼀. html和css
将导航这个导航条包裹在⼀个div中,这个div的position值为relative,⾼度为50px(导航条的⾼度为50px),宽度为100%,将最外层的div的position属性设置为relative是因为⼆级导航要根据这个div来定位。这个导航条的结构是⼆级嵌套⽆序列表。每⼀个⼀级导航项li都嵌套了它对应的⽆序列表。需要将嵌套的⽆序列表移除⽂档流。所以嵌套的⽆序列表的position值为absolute,top:50px(导航条的⾼度)。left:0;right:0;通过设置这些值可以使嵌套的⽆序列表宽度为浏览器视⼝的宽度。通过将li的display值设置inline-block并且将外层div的text-align设置为center使得导航项居中显⽰。
注:在这个案例中⼀定要将嵌套的⽆序列表的position的值设置为absolute,使它移除⽂档流。
html和css代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下拉菜单</title>
<link rel="stylesheet" type="text/css" href="index.css" rel="external nofollow" >
</head>
<body>
<div class='header'>
<ul class='outer' id='outer'>
<li class='outerList' id='outerList1'><a href='#' id='link1' class='link'>产品<span></span></a>
<ul class='inter' id='inter1'>
<li>
<a href='#'>
<img src='img/01fea55541ed73000001714a430253.jpg'>
<strong>纳斯</strong>
</a>
</li>
<li>
<strong>纯⾊</strong>
</a>
</li>
<li>
<a href='#'>
<img src='img/⽩胡⼦.jpg'>
<strong>保温杯</strong>
</a>
</li>
<li>
<a href='#'>
导航菜单<img src='img/宠物.jpg'>
<strong>设计周边</strong>
</a>
</li>
</ul>
</li>
<li class='outerList' id='outerList2'><a href='#' id='link2' class='link'>服务<span></span></a> <ul class='inter' id = 'inter2'>
<li>
<a href='#'>
<img src='img/狮⼦座.jpg'>
<strong>售后服务</strong>
</a>
</li>
<li>
<a href='#'>
<img src='img/莲花禅.jpg'>
<strong>设计师</strong>
</a>
</li>
</ul>
</li>
</ul>
</div>
<script type="text/javascript" src='index.js'></script>
</body>
</html>
css代码如下:
*{
padding: 0;
margin: 0;
}
.header{
position: relative;
width: 100%;
height: 50px;
background-color: #000000;
text-align: center;
z-index: 2;
}
.
header .outer li{
display: inline-block;
list-style: none;
}
.outerList{
height: 50px;
line-height: 50px;
}
.outerList a{
display: block;
padding: 0 15px;
color: #fff;
text-decoration: none;
}
.outerList:hover a{
color: #EDECEC;
}
.outerList .link span{
display: block;
height: 0;
position: relative;
top: -10px;
left: 0;
background-color: #fff;
}
.outerList:hover .link span{
height: 1px;
}
.outerList .inter{
position: absolute;
left: 0;
height: 0;
overflow: hidden;
top: 50px;
right: 0;
background-color:rgba(0,0,0,0.5);
}
.outerList .inter li{
margin-top: 30px;
}
.outerList .inter strong{
display:block;
height: 25px;
line-height: 25px;
text-align: center;
}
⼆. js部分
在js部分涉及到的知识主要有:设置定时器,清除定时器,mouseout和mouseover事件。
mouseout事件当⿏标从⼀个元素上移⼊另⼀个元素的上时,会在失去⿏标的那个元素上触发mouseout事件。获得⿏标的那个元素可能是失去⿏标的元素的⽗元素或⼦元素,获得⿏标的那个元素也可能位于失去⿏标元素的外部。当在⼀级导航项上触发mouseout事件时,我们需要判断获得⿏标的元素是不是⼀级导航项的⼦孙元素。当⼀个元素触发了mouseout事件时,去⿏标的元素为⽬标元素(target),获得⿏标的元素为相关元素(relatedTarget)。所以需要判断相关元素是否为⼀级导航项的⼦孙元素,如果是⼦孙元素,则相应的导航项的⼆级导航项⾼度不变。如果不是⼦孙元素,则相应的⼆级导航项消失。判断是否为⼦孙元素的代码如下:
var flag1 = false,flag2 = false;
if(relatedTarget !== null){
var parented = relatedTarget.parentNode;
do{
if(parented === outerList1 || relatedTarget === outerList1){
flag1 = true;
break;
}else if(parented === outerList2 || relatedTarget === outerList2){
flag2 = true;
break;
}else{
parented = parented.parentNode;
}
}while(parented !== null);
}
注:通过判断flag1和flag2的值来确定是否该把⼆级菜单的⾼度变为0,如果flag1的值为false则让outerList1对应的⼆级菜单消失,如果flag2为false则将outerList2对应的⼆级菜单消失。
mouseover事件当⿏标移⼊⼀个元素内部时,获得⿏标的元素上触发这个事件,获得⿏标的元素可能位于失去⿏标的外部,也可能位于失去⿏标元素的内部。获得⿏标的元素是⽬标元素,失去⿏标的元素为相关元素。在这个案例中我们只需要判断mouseover的⽬标元素,但是对于mouseout事件我们需要判断相关元素。
注:在⽀持DOM的浏览器中,mouseout和mouseover的相关元素都保存在事件对象(event)的relatedTagrget属性中,但是在IE浏览器中,对于mouseout事件⽽⾔,相关事件保持在事件对象(event)的toElement属性中,对于mouseover事件⽽⾔,相关事件保存在事件对象(event)的fromElement属性中。
设置定时器和清除定时器在这个案例中嵌套⽆序列表的消失和出现是通过改变它的⾼度实现的,它的⾼度是逐渐变化,所以我使⽤的setTimeout这个定时器,为了能够清除定时器还要将定时器标识保存在⼀个变量中。清除定时器的⽬的是为了防⽌当快速移动⿏标时嵌套⽆序列表的⾼度抖动(即:⼀个定时器⾥的回调函数让⾼度增加,另⼀个定时器的回调函数让⾼度减⼩)。
var untilEvent = {
addEvent:function(element,type,hander){
if(element.addEventListener){
element.addEventListener(type,hander,false);
}else if(element.attachEvent){
element.attachEvent('on'+type,hander);
}else{
element['on'+type] = hander;
}
},
getEvent:function(event){
return event?event:window.event;
},
getTarget:function(event){
return event.target||event.srcElement;
},
getRelated:function(event){
latedTarget){
//兼容DOM的浏览器将相关元素保持在relatedTarget属性中
latedTarget;
}else Element){
//在IE浏览器中mouseout事件的相关元素保存在toElement属性中
Element;
}else if(event.fromElement){
//在IE浏览器中mouseover事件的相关元素保持在fromElement属性中
return event.fromElement;
}else{
return null;
}
}
};
//下⾯这四个元素⽤于表⽰四个定时器的标识,最开始我只使⽤两个定时器,当快速移动时
//动画会乱。
var timeDec1,timeAdd1,timeAdd2,timeDec2;//定时器标识
function getOuter(){
var outer = ElementById('outer');
untilEvent.addEvent(outer,'mouseover',callBackOver);
untilEvent.addEvent(outer,'mouseout',callBackOut);
}
//mouseout事件:当⿏标从⼀个元素移⼊另⼀个元素时在⿏标离开的那个元素
//上触发,获得⿏标的元素可能在失去⿏标元素的外部也可能在失去⿏标元素的
//内部.所以需要判断mouseout事件的相关元素是否为外部li(即id为outerList或id为outerList2)元素//的⼦孙元素,如果是⼦孙元素,则内部⽆序列表⽆须收起。
function callBackOut(event){
var event = Event(event);
var relatedTarget = Related(event);
var outerList1 = ElementById('outerList1');
var inter1 = ElementById('inter1');
var outerList2 = ElementById('outerList2');
var inter2 = ElementById('inter2');
var flag1 = false,flag2 = false;
if(relatedTarget !== null){
var parented = relatedTarget.parentNode;
do{
if(parented === outerList1 || relatedTarget === outerList1){
flag1 = true;
break;
}else if(parented === outerList2 || relatedTarget === outerList2){
flag2 = true;
break;
}else{
parented = parented.parentNode;
}
}while(parented !== null);
}
if(!flag1){
var str1 = 'flag1';
changeHeightDec(inter1,timeAdd1,str1);
}
if(!flag2){
var str2 = 'flag2';
changeHeightDec(inter2,timeAdd2,str2);
}
}
var offHeight = 70;
var inverTimer = 10;
clearTimeout(timer);
change();
function change(){
var height = parseInt(element.style.height);
if(!height)height = 0;
if(height > 0){
if(height - offHeight > 0){
element.style.height = height - offHeight +'px';
}else{
element.style.height = 0+'px';
}
if(flag === 'flag1'){
timeDec1= setTimeout(change,inverTimer);
}else{
timeDec2 = setTimeout(change,inverTimer);
}
}
}
}
function callBackOver(event){
var event = Event(event);
var target = Target(event);
var inter1 = ElementById('inter1');
var inter2 = ElementById('inter2');
if(target.id == 'outerList1' || target.id == "link1"){
var str1 = "flag1";
changeHeight(inter1,timeDec1,str1);
}
if(target.id == 'outerList2' || target.id == 'link2'){
var str2 = "flag2";
changeHeight(inter2,timeDec2,str2);
}
}
function changeHeight(element,timer,flag){
var totalHeight = 160;
var inverHeight = 10;
var inverTimer = 10;
clearTimeout(timer);
//当⿏标移⼊时清除让内部ul长度减⼩的定时器,保证⿏标移⼊后
//内部ul长度⽴即增加
change();
function change(){
var height = parseInt(element.style.height);
if(!height) height = 0;
if(height < totalHeight){
if(height + inverHeight > totalHeight){
element.style.height = totalHeight + "px";
}else{
element.style.height = height + inverHeight +'px';
}
if(flag === 'flag1'){
timeAdd1 = setTimeout(change,inverTimer);
}else{
timeAdd2 = setTimeout(change,inverTimer);
}
}
}
}
untilEvent.addEvent(window,'load',getOuter);
以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论