在完成了上一节后,我打算再给菜单加上些动画效果,借助script.aculo.us框架里的effect.js,我完成了下拉菜单的动画效果版本。 网页的XHTML结构层仍然没有变化,JS行为层逻辑也和原来一样,只不过新加了两个内部函数,分别为动画显示和动画隐藏。构造函数有两个参数,前一个为导航的CLASS,后一个参数可选,为动画的参数对象,包括动画时间,动画类型及动画延迟时间。动画类型包括三种,0:Blind,1:Blind + Alpha,2:Slide。 为了实现动画效果,必须给每个菜单外部套上一个DIV用来做菜单的遮罩层,由于这个原因,这个版本在不改动结构层的前提下,是不能实现多级下拉菜单,只能是一级。 I deside to add some animation effects to the drop down menu besed on the previous chapter. With the effect.js of the script.aculo.us framework, I've done the animation edition of drop down menu. The Xhtml structure hasn't been changed and logic of javascript is also same with before. I only add two internal function, animation show and animation hide. The constructor has two arguments, the first is the class of the navigation, the second is an object which include the arguments of the animation, animation duration, animation types, delay duration. The types of the animation including three types: set 0 to be Blind, set 1 to be Blind plus Alpha, set 2 to be Slide. In order to implement animation effects, I should add a mask div to wrap menu. In this case, this script can't implement multi-leve menu without changing the structure of the Xhtml, it can only to be one level. 演示 | Demo: Blind: http://www.kxbd.com/mylab/080616dropdownmenu/index.htm Blind+Alpah: http://www.kxbd.com/mylab/080616dropdownmenu/index1.htm Slide: http://www.kxbd.com/mylab/080616dropdownmenu/index2.htm 程序代码 程序代码 var dropDownMenu = Class.create(); dropDownMenu.prototype = { initialize:function(cls,option){ this.cls = cls; this.option = Object.extend({dur:0.3,type:0,delayDur:0.2}, option || {}); this.dur = this.option.dur; this.type = this.option.type; this.delayDur = this.option.delayDur; this.delayID; this.init(); }, init:function(){ $$(this.cls).each(function(o){ var oH=o.down(1).getDimensions().height; //o.down(1).setStyle({opacity:'0'}); o.down(1).makeClipping().setStyle({height:'0px'}); if (this.type == 2){ o.down(2).setStyle({position: "absolute", bottom:oH+"px"}); } o.observe("mouseover",function(e){ /* if(this.subMenu&&this.subMenu!=o){ window.clearTimeout(this.delayID); this.mvHideMenu(this.subMenu.down(1),oH); } */ if(this.delayID&&this.subMenu==o){ window.clearTimeout(this.delayID); } if (o.down(1).getStyle('height')!=oH) { this.subMenu = o; this.mvShowMenu(o.down(1),this.dur,this.type,oH); } }.bindAsEventListener(this,o)); o.observe("mouseout",function(e){ this.delayID = this.mvHideMenu.delay(this.delayDur,o.down(1),this.dur,this.type,oH); }.bindAsEventListener(this,o)); }.bind(this)); }, mvShowMenu:function(element,dur,type,h){ var o = $(element); var dur = dur; var type = type; var oH = h; //o.show(); new Effect.Morph(o, { style: 'height:'+oH+'px', //style:{opacity:'1'}, transition:Effect.Transitions.linear, afterUpdateInternal: function(effect) { if (type == 2){ effect.element.down().setStyle({bottom:(oH - effect.element.clientHeight) + 'px' }); }else if(type == 1){ effect.element.setStyle({opacity: effect.element.clientHeight/oH }); } }, duration:dur }); return element; }, mvHideMenu:function(element,dur,type,h){ var o = $(element); var dur = dur; var type = type; var oH = h; new Effect.Morph(o, { style: 'height:0px', transition:Effect.Transitions.linear, afterUpdateInternal: function(effect) { if (type == 2){ effect.element.down().setStyle({bottom:(oH - effect.element.clientHeight) + 'px' }); }else if(type == 1){ effect.element.setStyle({opacity: effect.element.clientHeight/oH }); } }, afterFinish:function(effect){ //effect.element.hide(); }, duration:dur }); return element; } }; document.observe("dom:loaded",function(){ $$(".nav_sub").each(function(o){ o.wrap('div', { 'class': 'nav_sub_wrapper' }) }); new dropDownMenu(".nav_li"); });