做这个导航栏的初衷,是想在公司产品的后台界面里,模仿MAC OS X系统的dock效果,所谓dock,就是OS X桌面底部那条显眼的工具栏,我的UBUNTU桌面里也有类似的效果……
实际上我也没用过MAC,所以是凭想象做的,演示页面在此
右上角的导航栏是默认的效果,鼠标滑过时图标变大,会推挤旁边的图标。
下面第一排去掉了推挤效果。
第二排加入了左右移动的功能,图标的数量远远超出页面的宽度,只显示其中一部分,在导航栏上左右移动鼠标时,整个导航栏会向相反方向滑动,显示出隐藏的图标。
第三排把移动的操作改到了左右两侧的箭头,鼠标停留在箭头上时,导航栏就会向对应的方向滑动,鼠标离开箭头时滑动停止,当滑动到最末端的图标时,自动停止。
先实现导航栏的默认效果,HTML如下:
- <div class="iconbarout">
- <div id="iconbar0" class="iconbar" >
- <ul style="margin-left:0px;">
- <li>
- <a href="#">
- <img src="images/icon7.png" style="width:68px;height:68px;" onload="alphaPNG(this);" onmouseover="largeIcon(this);" onmouseout="reIcon(this);" />
- <span>link7</span>
- </a>
- </li>
- <li>
- <a href="#">
- <img src="images/icon6.png" style="width:68px;height:68px;" onload="alphaPNG(this);" onmouseover="largeIcon(this);" onmouseout="reIcon(this);" />
- <span>link6</span>
- </a>
- </li>
- </ul>
- </div>
- </div>
为了追求立体感,图标不能有背景色,所以必须用透明PNG图片,这里用<img>标签插入图片,是因为要实现图标的缩小放大效果(CSS背景里的图片只能控制位置,不能改变大小),图标的长宽要写在元素的style属性里,方便JS程序控制。
由于IE6不支持PNG的透明背景,必须用滤镜来做HACK才能达到一样的效果,而滤镜只能写在CSS的背景属性里…………为了解决这个矛盾,就要依靠JS了:
- function alphaPNG(png)
- {
- var aVersion=navigator.appVersion.split("MSIE");
- var version=parseInt(aVersion[1]);
- var pp=png.parentNode;
- if( (version>=5.5) && (version<7) && (document.body.filters) )
- {
- var mout=png.onmouseout.toString();
- var mover=png.onmouseover.toString();
- alphaHTML="<span style=/"cursor:pointer;filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=scale, src='"+png.src+"');display:block;width:"+png.style.width+";height:"+png.style.height+";/" οnmοuseοver=/""+mover.substring(mover.indexOf("{")+1,mover.lastIndexOf("}"))+"/" οnmοuseοut=/""+mout.substring(mout.indexOf("{")+1,mout.lastIndexOf("}"))+"/" ></span>";
- png.outerHTML=alphaHTML;
- }
- }
这个函数已经写在图片的onload事件里了,会在IMG标签的内容加载完后触发(这个事件虽好,也不能到处乱用,根据伟大的犀牛书V5, onload只支持body, frameset, img),函数先判断浏览器类型和版本(IE7支持透明PNG),先创建一个span元素,IMG标签的所有属性、事件都原样COPY到SPAN上,而 PNG图片则放到SPAN的背景里,用滤镜处理成透明,注意滤镜属性里必须要有sizingMethod=scale。最后用outerHTML(只有 IE支持)把该IMG替换成span。
导航栏的样式:
- .iconbarout
- {
- width:770px;
- position:absolute;
- top:40px;right:10px;
- }
- .iconbar{
- overflow:hidden;
- float:left;
- }
- .iconbar li{
- float:right;
- padding:0px;
- width:auto;
- text-align:center;
- margin:0 16px 0 0px;
- }
- .iconbar li span{
- color:#333;
- font-weight:600;
- width:auto;
- display:block;
- float:none;
- margin:0px auto;
- }
- .iconbar li a img{
- margin:0px auto;
- float:none;
- }
- .iconbar li a{
- text-align:center;
- float:none;
- margin:0px auto;
- }
- .iconbar li img{
- border:0px;
- float:left;
- }
这样就在IE和Firefox里实现一样的视觉效果了(这里存在一个问题,为了保证图标放大后的清晰度,初始的图标都是缩小的,在IE7和Firefox里都会看到一点锯齿,而IE6由于用了滤镜,缩小的图标边缘仍然是平滑的-_____-b)
接下来做鼠标滑过的放大缩小效果。JS的动画效果一般是利用setTimeout或setInterval的延迟功能,反复循环来实现的。为了避免这些图标在运行函数时发生冲突,我把缩放的动画效果封装到了一个类里:
- /* zoom class by Dexter.Yy
- ********************************************************/
- function animeZoom(ico,gWidth,gHeight,nWidth,nHeight)
- {
- this.png=ico;
- this.iheight=nHeight;
- this.iWidth=nWidth;
- this.goWidth=gWidth;
- this.goHeight=gHeight;
- this.rico;
- }
- animeZoom.prototype.zoomEvent=function()
- {
- if(this.iWidth<this.goWidth)
- {
- this.goEnlarge();
- }
- else if(this.iWidth>this.goWidth)
- {
- this.goReduce();
- }
- }
- animeZoom.prototype.goEnlarge=function()
- {
- this.png.style.width=this.goWidth+"px";
- this.png.style.height=this.goWidth+"px";
- }
- animeZoom.prototype.goReduce=function()
- {
- var obj=this;
- var h=parseInt(this.png.style.height);
- var w=parseInt(this.png.style.width);
- if(w>this.goWidth)
- {
- this.png.style.width=w-2+"px";
- this.png.style.height=h-2+"px";
- this.rico=setTimeout(function(){obj.goReduce();},30);
- }
- else
- {
- window.clearTimeout(this.rico);
- }
- }
使用时要传5个参数:目标对象、期望达到的宽度、期望达到的高度、原始宽度、原始高度,像这样:
- function largeIcon(png)
- {
- var lIco=new animeZoom(png,91,91,68,68);
- lIco.zoomEvent();
- }
- function reIcon(png)
- {
- var rIco=new animeZoom(png,68,68,91,91);
- rIco.zoomEvent();
- }
OK完工……如果是在FLASH里做这种推挤效果,可能还要写一大堆AS,但这里有CSS的浮动属性帮忙,就很省事……