DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> JavaScript實戰之帶收放動畫效果的導航菜單
JavaScript實戰之帶收放動畫效果的導航菜單
編輯:關於JavaScript     

雖然有很多插件可用,但為了共同提高,我做了一系列JavaScript實戰系列的實例,分享給大家,前輩們若有好的建議,請務必指出,免得誤人子弟啊!
今天是第一戰:帶收放動畫效果的菜單,效果如下圖:(樣式有點丑(-^-)) 
( 由於在寫本文時,用的編輯器不同,暫時添加不了演示效果,這裡有:最終完整代碼和演示 ) 

動畫效果:鼠標hover改變所有目標的背景和字體顏色,鼠標移動到‘首頁導航',顯示下面的分組菜單,分組菜單有子菜單,點擊可縮放,帶動畫過度效果!而且,可以隨便添加和刪除導航菜單和子菜單,不影響效果! 

如何實現呢? 

第一步:用什麼來實現菜單?HTML代碼設計如下,遵循JS代碼和HTML代碼分離的原則!這裡你看不到一句JS代碼 

未應用樣式之前是這個樣子的:很古老吧!!! 

第二步:CSS樣式。鼠標hover改變所有目標的背景和字體顏色,直接用CSS的transition和:hover,而其他的CSS樣式布局就不全部列舉了,大家自己動手吧,主要注意以下幾點: 

 #ul{
 ....
 z-index: 100;
 }
 #ul li{
 display: inline-block;
 position: relative;
 top: 0;
 left: -25px;
 width: 10%;
 min-width: 70px;
 height: 30px;
 text-align: center;
 line-height: 30px;
 border: 1px solid gray;
 border-radius:10px;
 background-color: aliceblue;
 cursor: pointer;
 -webkit-transition: all ease-in-out 0.3s;
 -moz-transition: all ease-in-out 0.3s;
 -ms-transition: all ease-in-out 0.3s;
 -o-transition: all ease-in-out 0.3s;
 transition: all ease-in-out 0.3s;
 }
 #ul li:hover{background-color: aquamarine;color: red;}
 ...
 .show-hide:hover{background-color: beige}
 .a-div{
 background-color: aquamarine;
 border-radius:10px;
 color: black;
 display: none;
 opacity: 0
 }
 .a{
 z-index: -1;
 display: block;
 ...
 } 

第三步:這一步是重點。如果給每個菜單選項和分組都添加事件監聽,個人覺得好麻煩,且代碼量肯定多不少,有沒有什麼辦法就在一個元素上加監聽就能實現呢?

答案肯定是有的,利用事件的冒泡機制!在父元素ul標簽上添加事件監聽,而在監聽函數裡直接改變觸發事件的元素樣式就可以了,就這麼簡單!

代碼如下:

var ul = document.getElementById('ul');
ul.addEventListener('mouseover',listener1,false);
ul.addEventListener('mouseout',listener2,false);
ul.addEventListener('click',listener3,false); 
 

 因為IE8及以下版本沒有addEventListener,如果要兼容,還得加attachEvent對應的代碼。

第四:主角登場!實現listener1、listener2、listener3監聽函數。

首先來最簡單的listener1函數,代碼如下:

function listener1(event){
 //event = event||window.event; //兼容IE8及以前版本
 var target = event.target||event.srcElement; //兼容IE8及以前版本
 if(target.tagName.toLowerCase() === 'li'){
 var div1 = target.getElementsByTagName('div')[0];
 div1.style.display = 'block';
 var i = 0;
 var id;
 (function foo(){
 if(i>=1){clearTimeout(id);id=null;return;}
 i+=0.2;
 div1.style.opacity = i;
 id = setTimeout(function(){clearTimeout(id);foo()},30);  
    })();  
 }
 } 

同樣,一切為了IE8及更舊版本。  

1.因為它的event沒有target屬性,只有相對應得srcElement屬性  

2.而這一句event = event||window.event;這裡其實是可以省略的,只有當用屬性來設置注冊事件監聽時,如ul.onmouseover = function(){},或<ul onmouseover='func'>,IE8及更舊版本只能通過window.event來取得當前的Event對象

好了,現在獲得了當前觸發事件的target,事情就簡單很多了,通過他就可以改變它自己和它的親戚!

下面是listener2函數,用在mouseout時觸發,主要是操控target的子元素DIV,代碼如下:

function listener2(event){
 //event = event||window.event;
 var target = event.target||event.srcElement;
 if(target.tagName.toLowerCase() === 'li'){
 var div1 = target.getElementsByTagName('div')[0];
 div1.onmouseover = function(){
 div1.style.display = 'block';
 div1.style.opacity = 1;
 };
 div1.onmouseout = function(){
 div1.style.display = 'none';
 div1.style.opacity = 0;
 };
 div1.style.display = 'none'; //這一組是為了實現當鼠標從上方出去時隱藏div1
 div1.style.opacity = 0;
 }
 } 

好了,到這裡,已經實現了大部分效果了,還有最後一步,那就是1號主角了:listener3函數,它主要負責鼠標點擊時的縮放效果!

實現原理:  

1.函數外面定義一個bool變量當做開關,鼠標點一下開,再點一下關;  

2.通過setTimeout來實現動畫效果,動態的改變子菜單的height和opacity屬性,還有display屬性;

完整代碼如下:

var bool = true;
 function listener3(event) {
 var event = event || window.event;
 var target = event.target || event.srcElement;
 if (target.className === 'show-hide') {
 var parent = target.parentElement;
 var adiv = parent.getElementsByClassName('a-div')[0];
 if (window.getComputedStyle(adiv,null).opacity>0.5){bool=false}else{bool=true}
 var height = 90,
 changeH,
 opacity,
 id;
 if (bool) {
 changeH = 0;
 opacity = 0;
 target.innerHTML = '財經 -';
 (function show() {
 if (changeH > height) {clearTimeout(id);return}
 changeH += 5;
 opacity += 0.06;
 //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);
 adiv.style.height = changeH + 'px';
 adiv.style.opacity = opacity;
 adiv.style.display = 'block';
 id = setTimeout(function () {
                     clearTimeout(id);
 show();
 }, 16.7);
 })();
 bool = false;
 } else {
 changeH = height;
 opacity = 1;
 target.innerHTML = '財經 +';
 (function hidden() {
 if (changeH < 0) {clearTimeout(id);adiv.style.display = 'none';return}
 changeH -= 10;
 opacity -= 0.11;
 //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);
 adiv.style.height = changeH + 'px';
 adiv.style.opacity = opacity;
 id = setTimeout(function () {
                     clearTimeout(id);
 hidden();
 }, 16.7);
 })();
 bool = true;
 }
 }
 }

注意幾點:  

1.記得清除setTimeout的ID,然後退出,否則死循環,如if (changeH < 0) {clearTimeout(id);adiv.style.display = 'none';return}  

2.setTimeout的延遲時間設置為16.7是因為符合屏幕的刷新率60FPS,看著舒服  

3.調試過程中,設置changeH和opacity的遞增遞減值時,記得打印出來,方便調試:

console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);  

4.最後,整個菜單的實現中,最關鍵的是下面這一句,如果沒有這一句,你無法完美實現所有功能,比如:你點開一組子菜單,然後移動到其它組點擊的時候,情況將有很大不同;而window.getComputedStyle用這個的原因是,首次打開時,點任意組的第一下都沒反應,因為直接通過event.target在點第一下時是取不到opacity值的。

if (window.getComputedStyle(adiv,null).opacity>0.5){bool=false}else{bool=true};

不過,IE9以下不支持getComputedStyle方法,IE的Element對象有currentStyle屬性;

XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved