JavaScript實戰(帶收放動畫效果的導航菜單)

来源:http://www.cnblogs.com/susufufu/archive/2016/08/13/5768402.html
-Advertisement-
Play Games

雖然有很多插件可用,但為了共同提高,我做了一系列JavaScript實戰系列的實例,分享給大家,前輩們若有好的建議,請務必指出,免得誤人子弟啊! ( 原創文章,轉摘請註明:蘇服:http://www.cnblogs.com/susufufu/p/5768402.html ) 今天是第一戰:帶收放動畫 ...


雖然有很多插件可用,但為了共同提高,我做了一系列JavaScript實戰系列的實例,分享給大家,前輩們若有好的建議,請務必指出,免得誤人子弟啊!

( 原創文章,轉摘請註明:蘇服:http://www.cnblogs.com/susufufu/p/5768402.html )

今天是第一戰:帶收放動畫效果的菜單,效果如下圖:(樣式有點醜(-^-))

動畫效果:滑鼠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屬性;
完整代碼如下:
 1 var bool = true;
 2             function listener3(event) {
 3                 var event = event || window.event;
 4                 var target = event.target || event.srcElement;
 5                 if (target.className === 'show-hide') {
 6                     var parent = target.parentElement;
 7                     var adiv = parent.getElementsByClassName('a-div')[0];
 8                     if (window.getComputedStyle(adiv,null).opacity>0.5){bool=false}else{bool=true}
 9                     var height = 90,
10                             changeH,
11                             opacity,
12                             id;
13                     if (bool) {
14                         changeH = 0;
15                         opacity = 0;
16                         target.innerHTML = '財經 -';
17                         (function show() {
18                             if (changeH > height) {clearTimeout(id);return}
19                             changeH += 5;
20                             opacity += 0.06;
21                             //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height);
22                             adiv.style.height = changeH + 'px';
23                             adiv.style.opacity = opacity;
24                             adiv.style.display = 'block';
25                             id = setTimeout(function () {
                     clearTimeout(id);
26 show(); 27 }, 16.7); 28 })(); 29 30 bool = false; 31 } else { 32 changeH = height; 33 opacity = 1; 34 target.innerHTML = '財經 +'; 35 (function hidden() { 36 if (changeH < 0) {clearTimeout(id);adiv.style.display = 'none';return} 37 changeH -= 10; 38 opacity -= 0.11; 39 //console.log('opacity:'+adiv.style.opacity+',height :'+adiv.style.height); 40 adiv.style.height = changeH + 'px'; 41 adiv.style.opacity = opacity; 42 id = setTimeout(function () {
                     clearTimeout(id);
43 hidden(); 44 }, 16.7); 45 })(); 46 bool = true; 47 } 48 } 49 }
註意幾點:
  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屬性;

如果你對CSS的處理不是很熟悉,看看我的總結:
用原生JS讀寫CSS樣式的方法總結
如果你想多瞭解setTimeout()方法的應用,看看這個:你真的知道setTimeout是如何運行的嗎
對於事件的處理機制,可以看看這個:DOM中的事件處理概覽與原理的全面剖析
好了,到此結束,有不對和更好的地方,歡迎指教!



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這兩天查了好多eval()的資料,結果還是很模糊,但是把自己知道的寫下來了! ...
  • Ajax 完整教程 第 1 頁 Ajax 簡介Ajax 由 HTML、JavaScript™ 技術、DHTML 和 DOM 組成,這一傑出的方法可以將笨拙的 Web 界面轉化成交互性的 Ajax 應用程式。本文的作者是一位 Ajax 專家,他演示了這些技術如何協同工作 —— 從總體概述到細節的討論 ...
  • HTML 什麼是瀏覽器什麼是伺服器? 可以顯示伺服器中的html文件。 可以讓用戶與這些文件交互。 特點: 處理請求。 必須保證二十四小時開機狀態。 請求協議:http協議: Url的組成:協議://伺服器的ip地址:埠號/請求頁面。 原來瀏覽器所做的事情是將伺服器響應回來的response進行從 ...
  • 例一 var x=10;全局變數(開闢空間)function outer(){x=20;//此處未聲明變數(未開闢空間),只給全局變數聲明瞭,此處賦值會把全局變數開闢的存儲空間的值替換掉(全局變數中的x替換成20)。function inner(){x=30;//此處未聲明變數(未開闢空間),只給全 ...
  • { "total": 16, "rows":[ { "name": "張三", "email": "[email protected]", "date": "2016-08-13" }, { "name": "李四", "email": "[email protected]", "date": " ...
  • web前端之HTML的大框架 body元素與frameset元素 對於從事html的人員來說,我們一般熟悉的框架是先聲明html ,然後在<html>標簽對里包著<head>標簽對和<body>標簽對,body元素定義文檔的主體,包含文檔的所有內容(比如文本、超鏈接、圖像、表格和列表等等)。而我們想 ...
  • 一、表單事件: 一、表單事件: input事件當<input>、<textarea>的值發生變化時觸發。此外,打開contenteditable屬性的元素,只要值發生變化,也會觸發input事件。input事件的一個特點,就是會連續觸發,比如用戶每次按下一次按鍵,就會觸發一次input事件。 inp ...
  • 事件是一種非同步編程的實現方式,本質上是程式各個組成部分之間的通信,DOM支持大量的事件; 本文通過這幾點向大家詳細解析事件處理的基本原理:事件類型、事件目標、事件處理程式、事件對象、事件傳播 最後再向大家介紹Event對象; (原創文章,轉摘請註明:蘇服:http://www.cnblogs.com ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...