原生JS實(shí)現(xiàn)導(dǎo)航下拉菜單效果
這個(gè)導(dǎo)航下拉菜單需要實(shí)現(xiàn)的功能是:下拉菜單的寬度與瀏覽器視口的寬度一樣寬;一級(jí)導(dǎo)航只有兩項(xiàng),當(dāng)鼠標(biāo)移到一級(jí)導(dǎo)航上的導(dǎo)航項(xiàng)時(shí),相應(yīng)的二級(jí)導(dǎo)航出現(xiàn)。在本案例中通過(guò)改變二級(jí)導(dǎo)航的高度來(lái)實(shí)現(xiàn)二級(jí)導(dǎo)航的顯示和消失。為了便于理解我畫了一個(gè)圖,如下:
在這個(gè)案例主要用到的知識(shí)有:設(shè)置定時(shí)器,清除定時(shí)器,mouseout和mouseover事件,另外還有css中position相關(guān)知識(shí)。本案例分為兩部分講解。第一部分html和css,第二部分js。
一. html和css
將導(dǎo)航這個(gè)導(dǎo)航條包裹在一個(gè)div中,這個(gè)div的position值為relative,高度為50px(導(dǎo)航條的高度為50px),寬度為100%,將最外層的div的position屬性設(shè)置為relative是因?yàn)槎?jí)導(dǎo)航要根據(jù)這個(gè)div來(lái)定位。這個(gè)導(dǎo)航條的結(jié)構(gòu)是二級(jí)嵌套無(wú)序列表。每一個(gè)一級(jí)導(dǎo)航項(xiàng)li都嵌套了它對(duì)應(yīng)的無(wú)序列表。需要將嵌套的無(wú)序列表移除文檔流。所以嵌套的無(wú)序列表的position值為absolute,top:50px(導(dǎo)航條的高度)。left:0;right:0;通過(guò)設(shè)置這些值可以使嵌套的無(wú)序列表寬度為瀏覽器視口的寬度。通過(guò)將li的display值設(shè)置inline-block并且將外層div的text-align設(shè)置為center使得導(dǎo)航項(xiàng)居中顯示。
注:在這個(gè)案例中一定要將嵌套的無(wú)序列表的position的值設(shè)置為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'>產(chǎn)品<span></span></a> <ul class='inter' id='inter1'> <li> <a href='#'> <img src='img/01fea55541ed73000001714a430253.jpg'> <strong>納斯</strong> </a> </li> <li> <a href='#'> <img src='img/thumb_image3.jpg'> <strong>純色</strong> </a> </li> <li> <a href='#'> <img src='img/白胡子.jpg'> <strong>保溫杯</strong> </a> </li> <li> <a href='#'> <img src='img/寵物.jpg'> <strong>設(shè)計(jì)周邊</strong> </a> </li> </ul> </li> <li class='outerList' id='outerList2'><a href='#' id='link2' class='link'>服務(wù)<span></span></a> <ul class='inter' id = 'inter2'> <li> <a href='#'> <img src='img/獅子座.jpg'> <strong>售后服務(wù)</strong> </a> </li> <li> <a href='#'> <img src='img/蓮花禪.jpg'> <strong>設(shè)計(jì)師</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; width: 100%; 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部分涉及到的知識(shí)主要有:設(shè)置定時(shí)器,清除定時(shí)器,mouseout和mouseover事件。
mouseout事件當(dāng)鼠標(biāo)從一個(gè)元素上移入另一個(gè)元素的上時(shí),會(huì)在失去鼠標(biāo)的那個(gè)元素上觸發(fā)mouseout事件。獲得鼠標(biāo)的那個(gè)元素可能是失去鼠標(biāo)的元素的父元素或子元素,獲得鼠標(biāo)的那個(gè)元素也可能位于失去鼠標(biāo)元素的外部。當(dāng)在一級(jí)導(dǎo)航項(xiàng)上觸發(fā)mouseout事件時(shí),我們需要判斷獲得鼠標(biāo)的元素是不是一級(jí)導(dǎo)航項(xiàng)的子孫元素。當(dāng)一個(gè)元素觸發(fā)了mouseout事件時(shí),去鼠標(biāo)的元素為目標(biāo)元素(target),獲得鼠標(biāo)的元素為相關(guān)元素(relatedTarget)。所以需要判斷相關(guān)元素是否為一級(jí)導(dǎo)航項(xiàng)的子孫元素,如果是子孫元素,則相應(yīng)的導(dǎo)航項(xiàng)的二級(jí)導(dǎo)航項(xiàng)高度不變。如果不是子孫元素,則相應(yīng)的二級(jí)導(dǎo)航項(xiàng)消失。判斷是否為子孫元素的代碼如下:
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); }
注:通過(guò)判斷flag1和flag2的值來(lái)確定是否該把二級(jí)菜單的高度變?yōu)?,如果flag1的值為false則讓outerList1對(duì)應(yīng)的二級(jí)菜單消失,如果flag2為false則將outerList2對(duì)應(yīng)的二級(jí)菜單消失。
mouseover事件當(dāng)鼠標(biāo)移入一個(gè)元素內(nèi)部時(shí),獲得鼠標(biāo)的元素上觸發(fā)這個(gè)事件,獲得鼠標(biāo)的元素可能位于失去鼠標(biāo)的外部,也可能位于失去鼠標(biāo)元素的內(nèi)部。獲得鼠標(biāo)的元素是目標(biāo)元素,失去鼠標(biāo)的元素為相關(guān)元素。在這個(gè)案例中我們只需要判斷mouseover的目標(biāo)元素,但是對(duì)于mouseout事件我們需要判斷相關(guān)元素。
注:在支持DOM的瀏覽器中,mouseout和mouseover的相關(guān)元素都保存在事件對(duì)象(event)的relatedTagrget屬性中,但是在IE瀏覽器中,對(duì)于mouseout事件而言,相關(guān)事件保持在事件對(duì)象(event)的toElement屬性中,對(duì)于mouseover事件而言,相關(guān)事件保存在事件對(duì)象(event)的fromElement屬性中。
設(shè)置定時(shí)器和清除定時(shí)器在這個(gè)案例中嵌套無(wú)序列表的消失和出現(xiàn)是通過(guò)改變它的高度實(shí)現(xiàn)的,它的高度是逐漸變化,所以我使用的setTimeout這個(gè)定時(shí)器,為了能夠清除定時(shí)器還要將定時(shí)器標(biāo)識(shí)保存在一個(gè)變量中。清除定時(shí)器的目的是為了防止當(dāng)快速移動(dòng)鼠標(biāo)時(shí)嵌套無(wú)序列表的高度抖動(dòng)(即:一個(gè)定時(shí)器里的回調(diào)函數(shù)讓高度增加,另一個(gè)定時(shí)器的回調(diào)函數(shù)讓高度減?。?/p>
js代碼如下:
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){ if(event.relatedTarget){ //兼容DOM的瀏覽器將相關(guān)元素保持在relatedTarget屬性中 return event.relatedTarget; }else if(event.toElement){ //在IE瀏覽器中mouseout事件的相關(guān)元素保存在toElement屬性中 return event.toElement; }else if(event.fromElement){ //在IE瀏覽器中mouseover事件的相關(guān)元素保持在fromElement屬性中 return event.fromElement; }else{ return null; } } }; //下面這四個(gè)元素用于表示四個(gè)定時(shí)器的標(biāo)識(shí),最開始我只使用兩個(gè)定時(shí)器,當(dāng)快速移動(dòng)時(shí) //動(dòng)畫會(huì)亂。 var timeDec1,timeAdd1,timeAdd2,timeDec2;//定時(shí)器標(biāo)識(shí) function getOuter(){ var outer = document.getElementById('outer'); untilEvent.addEvent(outer,'mouseover',callBackOver); untilEvent.addEvent(outer,'mouseout',callBackOut); } //mouseout事件:當(dāng)鼠標(biāo)從一個(gè)元素移入另一個(gè)元素時(shí)在鼠標(biāo)離開的那個(gè)元素 //上觸發(fā),獲得鼠標(biāo)的元素可能在失去鼠標(biāo)元素的外部也可能在失去鼠標(biāo)元素的 //內(nèi)部.所以需要判斷mouseout事件的相關(guān)元素是否為外部li(即id為outerList或id為outerList2)元素 //的子孫元素,如果是子孫元素,則內(nèi)部無(wú)序列表無(wú)須收起。 function callBackOut(event){ var event = untilEvent.getEvent(event); var relatedTarget = untilEvent.getRelated(event); var outerList1 = document.getElementById('outerList1'); var inter1 = document.getElementById('inter1'); var outerList2 = document.getElementById('outerList2'); var inter2 = document.getElementById('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); } } function changeHeightDec(element,timer,flag){ 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 = untilEvent.getEvent(event); var target = untilEvent.getTarget(event); var inter1 = document.getElementById('inter1'); var inter2 = document.getElementById('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); //當(dāng)鼠標(biāo)移入時(shí)清除讓內(nèi)部ul長(zhǎng)度減小的定時(shí)器,保證鼠標(biāo)移入后 //內(nèi)部ul長(zhǎng)度立即增加 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);
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 利用Js+Css實(shí)現(xiàn)折紙動(dòng)態(tài)導(dǎo)航效果實(shí)例源碼
- JS+CSS實(shí)現(xiàn)鼠標(biāo)滑過(guò)時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條效果
- javascript實(shí)現(xiàn)的鼠標(biāo)懸停時(shí)動(dòng)態(tài)翻滾的導(dǎo)航條
- JS實(shí)現(xiàn)移動(dòng)端可折疊導(dǎo)航菜單(現(xiàn)代都市風(fēng))
- JS無(wú)限級(jí)導(dǎo)航菜單實(shí)現(xiàn)方法
- vuejs 切換導(dǎo)航條高亮(路由菜單高亮)的方法示例
- js實(shí)現(xiàn)水平滾動(dòng)菜單導(dǎo)航
- 如何使用wheelnav.js構(gòu)建酷炫的動(dòng)態(tài)導(dǎo)航菜單
相關(guān)文章
JS使用正則表達(dá)式獲取小括號(hào)、中括號(hào)及花括號(hào)內(nèi)容的方法示例
這篇文章主要介紹了JS使用正則表達(dá)式獲取小括號(hào)、中括號(hào)及花括號(hào)內(nèi)容的方法,涉及javascript針對(duì)三種括號(hào)正則匹配的相關(guān)操作技巧,需要的朋友可以參考下2018-06-06js中編碼函數(shù):escape,encodeURI與encodeURIComponent詳解
escape(), encodeURI()和encodeURIComponent()是在Javascript中用于編碼字符串的三個(gè)常用的方法,而他們之間的異同卻困擾了很多的Javascript初學(xué)者,這篇文章詳細(xì)的給大家介紹了js中編碼函數(shù):escape,encodeURI與encodeURIComponent的相關(guān)資料,需要的朋友可以參考下。2017-03-03js兼容pc端瀏覽器并有多種彈出小提示的手機(jī)端浮層控件實(shí)例
這篇文章主要介紹了js兼容pc端瀏覽器并有多種彈出小提示的手機(jī)端浮層控件,實(shí)例分析了javascript多種彈出層效果的實(shí)現(xiàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04JavaScript 正則表達(dá)式中g(shù)lobal模式的特性
這篇文章主要介紹了JavaScript 正則表達(dá)式中g(shù)lobal模式的特性 的相關(guān)資料,需要的朋友可以參考下2016-02-02基于iScroll實(shí)現(xiàn)下拉刷新和上滑加載效果
這篇文章主要為大家詳細(xì)介紹了基于iScroll實(shí)現(xiàn)下拉刷新和上滑加載效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07JS簡(jiǎn)單循環(huán)遍歷json數(shù)組的方法
這篇文章主要介紹了JS簡(jiǎn)單循環(huán)遍歷json數(shù)組的方法,結(jié)合實(shí)例形式簡(jiǎn)單分析了JavaScript循環(huán)遍歷json數(shù)組的方法,并提供了jQuery遍歷json的方法,需要的朋友可以參考下2016-04-04使用Layer組件彈出多個(gè)對(duì)話框(非嵌套)與關(guān)閉及刷新的例子
今天小編就為大家分享一篇使用Layer組件彈出多個(gè)對(duì)話框(非嵌套)與關(guān)閉及刷新的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09