JavaScript 動畫效果緩慢二級下拉選單

admin發表於2019-01-27

本章節分享一段程式碼例項,實現了滑鼠懸浮動畫效果的緩慢下拉出現二級導航選單效果。

下面就給出這個程式碼並且做出詳細的分析,程式碼如下:

[HTML] 純文字檢視 複製程式碼
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style type="text/css">
*{
  margin:0;
  padding:0;
  font-style:normal;font-family:宋體;
}
body{
  text-align:center;
  font-size:14px;
}
#content{
  margin:0 auto;
  width:600px;
}
#content #nav{
  background:#006400;
  height:32px;
  margin-top:10px;
}
#content #nav ul{list-style:none;}
#content #nav ul li{
  float:left;
  width:100px;
  line-height:32px;
  position:relative;
}
#nav div{
  width:100px;
  position:absolute;
  left:0px;
  padding-bottom:0px;
  background:#006400;
  float:left;
  height:0;
  overflow:hidden;
}
#content #nav li .a{
  text-decoration:none;
  color:#00CD00;
  line-height:32px;
  display:block;
  border-right:1px solid #009800;
}
#nav div a{
  text-decoration:none;
  color:#00CD00;
  line-height:26px;
  display:block;
}
#nav div a:hover{background:#005400;}
</style>
<script type="text/javascript">
var paddingbottom=20;
var defaultHeight = 0;
function drop(obj, ivalue,timer) {
  var a=obj.offsetHeight;
  var speed=(ivalue-obj.offsetHeight)/8;
  if(ivalue==0){
    a+=Math.floor(speed);
  }else{
    a+=Math.ceil(speed);
  }
  obj.style.height = a + "px";
  if (ivalue == obj.offsetHeight) { 
    clearInterval(timer)
  }
}
window.onload=function(){
  var supnav=document.getElementById("supnav");
  var nav=document.getElementById("nav");
  var lis=document.getElementsByTagName("li");
  var subnavs=nav.getElementsByTagName("div");
  for (var index = 0; index < lis.length; index++) {
 
    lis[index].index = index;
    lis[index].timer = null;
    lis[index].onmouseover = function () {
      var osubnav=subnavs[this.index];
      var sublinks=osubnav.getElementsByTagName("a");
      if(osubnav.firstChild.tagName==undefined){
        var itarheight=parseInt(osubnav.childNodes[1].offsetHeight)*sublinks.length+paddingbottom;
      }
      else{
        var itarheight=parseInt(osubnav.firstChild.offsetHeight)*sublinks.length+paddingbottom;
      }
      clearInterval(this.timer);
      this.timer=setInterval(function(){drop(osubnav,itarheight);},30);
    }
    lis[index].onmouseout=function(){
      var osubnav = subnavs[this.index];
      clearInterval(this.timer);
      this.timer = setInterval(function () { drop(osubnav, defaultHeight, this.time); }, 30);
    }
  }
}
</script>
</head>
<body>
<div id="content">
  <div id="nav">
    <ul id="supnav">
      <li>
        <a href="#" class="a">螞蟻部落一</a>
        <div>
          <a href="#">選單測試1</a>
          <a href="#">選單測試1</a>
          <a href="#">選單測試1</a>
        </div>
      </li>
      <li>
        <a href="#" class="a">螞蟻部落二</a>
        <div>
          <a href="#">選單測試2</a>
          <a href="#">選單測試2</a>
          <a href="#">選單測試2</a>
        </div>
      </li>
      <li>
        <a href="#" class="a">螞蟻部落三</a>
        <div>
          <a href="#">選單測試3</a>
          <a href="#">選單測試3</a>
          <a href="#">選單測試3</a>
          <a href="#">選單測試3</a>
          <a href="#">選單測試3</a>
        </div>
      </li>
      <li>
        <a href="#" class="a">螞蟻部落四</a>
        <div>
          <a href="#">選單測試4</a>
          <a href="#">選單測試4</a>
          <a href="#">選單測試4</a>
        </div>
      </li>
      <li>
        <a href="#" class="a">螞蟻部落五</a>
        <div>
          <a href="#">選單測試5</a>
          <a href="#">選單測試5</a>
          <a href="#">選單測試5</a>
          <a href="#">選單測試5</a>
        </div>
      </li>
      <li>
        <a href="#" class="a">螞蟻部落六</a>
        <div>
          <a href="#">選單測試6</a>
          <a href="#">選單測試6</a>
          <a href="#">選單測試6</a>
        </div>
      </li>
    </ul>
  </div>
</div>
</body>
</html>

上面的程式碼實現了我們的要求,下面介紹一下它的實現過程。

一.程式碼註釋:

(1).var paddingbottom=20,宣告一個變數,用來作為下拉選單最後的連結和底部的距離。

(2).var defaultHeight=0,宣告一個變數並賦初值為0,這個是指下拉選單的預設高度。

(3).function drop(obj,ivalue,timer){},此方法實現了下拉選單的動畫效果,也就是緩慢下拉或者緩慢收縮,第一個引數規定二級下拉選單,在這裡是div元素,第二個引數規定目標高度值,第三個引數是定時器函式的標識。

(4).var a=obj.offsetHeight,獲取div元素當前的高度。

(5).var speed=(ivalue-obj.offsetHeight)/8,計算每次尺寸變化的幅度,因為元素的高度是時刻變化的,所以具有緩衝效果。

(6).if(ivalue==0){

  a+=Math.floor(speed);

}else{

  a+=Math.ceil(speed);

},如果是收縮的話,那麼就使用下舍入,如果是下拉就使用上舍入。

這麼寫的目的是能夠讓動畫完全執行完畢,下面就以下拉為例子做一下介紹。

目標高度是98,如果當前高度是90的話,因為需要除以8,所以這個時候的速度是1。

當再次執行的時候,目標高度依然是98,但是當前元素高度是91,7除以8就是小於1的數,那麼就需要上舍入獲取1,元素的當前高度才能繼續增大,直到達到目標高度。

(7).if(ivalue==obj.offsetHeight){

  clearInterval(timer)

},如果元素的當前高度達到目標高度就停止定時器函式的執行。

(8).obj.style.height=a+"px",設定元素的高度。

(9).window.onload=function(){},當文件內容完全載入完畢再去執行函式中的程式碼。

(10).var supnav=document.getElementById("supnav"),獲取指定id的元素物件。

(11).var nav=document.getElementById("nav"),同上。

(12).var lis=document.getElementsByTagName("li"),後去li元素集合。

(13).var subnavs=nav.getElementsByTagName("div"),獲取div元素集合。

(14).for(var index=0;index<lis.length;index++){},遍歷li元素集合中的每一個元素。

(15).lis[index].index=index,為當前元素物件新增一個index屬性,並賦值為index,也就是當前索引。

(16).lis[index].timer = null,為當前物件新增一個timer屬性,用來儲存定時器函式的標識。

(17).lis[index].onmouseover=function(){

  var osubnav=subnavs[this.index];

  var sublinks=osubnav.getElementsByTagName("a");

  if(osubnav.firstChild.tagName==undefined){

    var itarheight=parseInt(osubnav.childNodes[1].offsetHeight)*sublinks.length+paddingbottom;

  }

  else{

    var itarheight=parseInt(osubnav.firstChild.offsetHeight)*sublinks.length+paddingbottom;

  }

  clearInterval(this.timer);

  timer=setInterval(function(){drop(osubnav,itarheight);},30);

},為元素註冊onmouseover事件處理函式。

首先獲取對應索引的div元素,也就是二級下拉選單。

然後獲取二級下來選單中的所有連線a元素。

判斷語句很重要,因為firstChild獲取的節點可能是空格和換行,他們會被當做文字節點來處理。

所以需要進行一下判斷,如果不具有tagName屬性值,難就是文字節點,就要獲取osubnav子節點中的第二個節點(節點的索引是從0開始)。

然後通過offsetHeight獲取連結的高度,再乘以連結的數目,最後加上paddingbottom,就是div的高度了(最大高度)。

當然如果具有tagName屬性值,第一個子節點就是連結a,直接進行相關計算即可。

clearInterval(this.timer),它的作用是停止當前正在進行的動畫,這樣可以防止多個定時器函式同事執行的問題。比如我們快速連續兩次滑鼠懸浮於同一下拉選單,如果不停止上一個定時器函式,那麼兩個定時器函式就會疊加。

this.timer=setInterval(function(){drop(osubnav,itarheight);},30),使用定時器函式不斷呼叫指定函式。

二.相關閱讀:

(1).offsetHeight參閱JavaScript offsetHeight一章節。

(2).Math.floor()參閱JavaScript Math.floor()一章節。

(3).Math.ceil()參閱JavaScript Math.ceil()一章節。

(4).clearInterval()參閱window.clearInterval()一章節。

(5).setInterval()參閱setInterval()一章節。

(6).getElementsByTagName()參閱document.getElementsByTagName()一章節。

(7).onmouseover事件參閱JavaScript mouseover事件一章節。

(8).firstChild參閱JavaScript firstChild屬性一章節。

(9).tagName參閱JavaScript tagName屬性一章節。

(10).childNodes參閱JavaScript childNodes一章節。

(11).parseInt()參閱JavaScript parseInt()一章節。

(12).onmouseout參閱JavaScript mouseout事件一章節。

相關文章