Skip to content

2010年07月25日

JavaScript菜单循序渐进

说起菜单不同的人可能有不同感受,有的人感觉这个很有趣,做菜单是一件很好玩的事;也有的人会对它不屑一顾,认为这些都是雕虫小技;还有一部分人会认为,这个完全没必要仔细看,一切都可以拿来主义,网上一搜一大把,焉用亲自去写?

本文并不是什么很高深的见解或者观点独到,只是想从一些示例来寻找菜单制作的思路,掌握了思想就可以融会变通,想要什么样的菜单,只要想出来,就可以尝试去实现你的创意。

有人一看,说你用JavaScript做菜单,这个太不友好了,现在纯CSS的菜单到处都是。的确如此,我blog里也有很多纯CSS菜单的demo,但纯CSS做出来的菜单毕竟效果很有限,有些创意但靠CSS可能无法实现,用JavaScript写菜单也是一种尝试,可以实现很炫的效果(网上JavaScript模仿flash的效果很多)。

但由于JavaScript里事件具有冒泡的特性,在处理菜单的时候,往往被冒泡搞的很头疼,特别是给菜单加上动画特效之后,更是让很多人郁闷,有人可能会用timer或者坐标判断来解决这个问题,但其实都不理想,网上还有老外写的一个jQuery插件,专门用于解决这个问题,可以说JavaScript做菜单并不是一件小事。

好了,闲话少说,开始第一步,做一个简单的下拉菜单:

用到的HTML代码:

程序代码 程序代码

<ul id="nav">
  <li>
     <a href="#">江苏省</a>
     <div class="child_menu">
          <a href="#">南京</a>
          <a href="#">苏州</a>
          <a href="#">无锡</a>
          <a href="#">常州</a>
          <a href="#">镇江</a>
          <a href="#">徐州</a>
     </div>
  </li>
  <li>
     <a href="#">浙江省</a>
     <div class="child_menu">
          <a href="#">杭州</a>
          <a href="#">宁波</a>
     </div>
  </li>
  <li>
     <a href="#">福建省</a>
     <div class="child_menu">
          <a href="#">厦门</a>
          <a href="#">福州</a>
          <a href="#">泉州</a>
     </div>
  </li>
  <li>
     <a href="#">广东省</a>
     <div class="child_menu">
          <a href="#">广州</a>
          <a href="#">深圳</a>
          <a href="#">东莞</a>
          <a href="#">潮州</a>
     </div>
  </li>
  <li>
     <a href="#">山东省</a>
     <div class="child_menu">
          <a href="#">青岛</a>
          <a href="#">威海</a>
          <a href="#">泰安</a>
          <a href="#">济南</a>
          <a href="#">德州</a>
     </div>
  </li>
</ul>



CSS样式代码:

程序代码 程序代码

#nav{ width:500px; margin:0px auto; list-style:none; font-size:12px; text-align:center; line-height:26px;}
#nav li{ width:100px; float:left;}
#nav li a{ display:block; width:99px; border-bottom:#FFFFFF 1px solid; text-decoration:none; background:#333333; height:26px; color:#CCCCCC;}
#nav li a:hover{ background:#CCCCCC; color:#333333;}
#nav li div{ display:none;}



后面的JavaScript代码都是引用上面的HTML和样式,示例使用了JQuery,如果要查看效果,运行后需要刷新一下页面。

基本菜单效果的实现:

程序代码 程序代码
<script type="text/javascript">
var nav_main=$("#nav>li>a");
var nav_child=$("#nav>li>div");
nav_main.each(function(i){
   $(this).mouseover(function(){
               basic.show(i);
               })
          .mouseout(function(){
               basic.hidden(i);
               });
});
nav_child.each(function(i){
   $(this).mouseover(function(){
               basic.show(i);
               })
          .mouseout(function(){
               basic.hidden(i);
               });
});

var basic={
   show:function(i){nav_child.eq(i).show();},
   hidden:function(i){nav_child.eq(i).hide();}
}
</script>



查看效果:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]




2. 增加一个小效果,菜单弹出的动画效果

程序代码 程序代码

var senior={
   show:function(i){
       nav_child.eq(i).show("fast");
   },
   hidden:function(i){
       nav_child.eq(i).stop(true,true);
       nav_child.eq(i).hide();
   }
}



查看示例:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



3. 让菜单收缩也实现动画效果

程序代码 程序代码

var senior={
   show:function(i){
       nav_child.eq(i).show("fast");
   },
   hidden:function(i){
       nav_child.eq(i).stop(true,true);
       nav_child.eq(i).hide("fast");
   }
}



查看示例:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



上面的效果看起来似乎还不够完美,应该让鼠标从子菜单上移走时,也是动画收回效果。

4. 进一步完善菜单的动画效果

运行查看效果:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



似乎还不够好,show和hidden函数写了两遍,分别在basic和senior对象里,能不能合成一个呢?

5. 再次进行改进,利用windows事件消除冒泡造成的菜单闪烁问题。

对senior对象进行改进:

程序代码 程序代码
var senior={
   getEvent:function(){
         if(window.event){
               return this.formatEvent(window.event);
          }else{
               return this.getEvent.caller.arguments[0];  
          }
   },
   formatEvent:function(e){
        if(e.type=="mouseout"){
           e.relatedTarget=e.toElement;    
        }else if(e.type=="mouseover"){
           e.relatedTarget=e.fromElement;    
        }        
        e.stopPropagation=function(){this.cancelBubble=true;};        
        e.target=e.srcElement;
        return e;
   },
   show:function(e,i){
       nav_child.eq(i).stop(true,true);
       var oEvent=this.getEvent();
       if(oEvent.relatedTarget.tagName!='A'||$.inArray(oEvent.relatedTarget,nav_main)>-1){
       nav_child.eq(i).show("fast");
       }
   },
   hidden:function(e,i){      
       nav_child.eq(i).stop(true,true);
       var oEvent=this.getEvent();
       if(oEvent.relatedTarget.tagName!='A'||$.inArray(oEvent.relatedTarget,nav_main)>-1){
       nav_child.eq(i).hide("fast");
       }
   }
}



查看示例效果:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



有了上面的模式之后,就可以很容易变换出其它的动画效果,比如把show换成slideDown,动画就变成了手风琴的效果,如下:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



只需要稍微修改一下CSS,就变成了横向菜单

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



多行菜单

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



更精简的版本

上周交流会我提出了这个问题,虽然大家各种观点都有,但最后还是得到一点更好的思路,那就是hover,用可以省去很多的麻烦,思路也变得更简单。

示例效果:

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



hover的魅力惊人

有了这个思路,灵活度就大了很多。

HTML代码


[Ctrl+A 全部选择 提示:你可先修改部分代码,再按运行]



JQuery div:hover  CSS3 animation


欢迎转载,转载请注明: 转载自田园牧歌

本文链接地址: JavaScript菜单循序渐进

相关阅读

Read more from 前端开发

Share your thoughts, post a comment.

(required)
(required)

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments