My child,
I watch with pride, as you grew into a weapon of righteousness.
Remember, Our line has always ruled with wisdom, and strength.
And i know,
You would show restraint, when you exercising your great power.
But the truest victory my son,
Is stiring hearts of your people.
For when my days have come to an end,
You, Shall be king.

- King Terenas Menethil IIWorld of Warcraft

YY流界面之动态图标导航栏

March 3, 2007

做这个导航栏的初衷,是想在公司产品的后台界面里,模仿MAC OS X系统的dock效果,所谓dock,就是OS X桌面底部那条显眼的工具栏,我的UBUNTU桌面里也有类似的效果……

实际上我也没用过MAC,所以是凭想象做的,演示页面在此

右上角的导航栏是默认的效果,鼠标滑过时图标变大,会推挤旁边的图标。
下面第一排去掉了推挤效果。
第二排加入了左右移动的功能,图标的数量远远超出页面的宽度,只显示其中一部分,在导航栏上左右移动鼠标时,整个导航栏会向相反方向滑动,显示出隐藏的图标。
第三排把移动的操作改到了左右两侧的箭头,鼠标停留在箭头上时,导航栏就会向对应的方向滑动,鼠标离开箭头时滑动停止,当滑动到最末端的图标时,自动停止。

先实现导航栏的默认效果,HTML如下:

  1. <div class="iconbarout">
  2.  
  3. <div id="iconbar0" class="iconbar" >
  4.  
  5.  <ul style="margin-left:0px;">
  6.  
  7.  <li>
  8.   <a href="#">
  9.  
  10.    <img src="images/icon7.png" style="width:68px;height:68px;" onload="alphaPNG(this);" onmouseover="largeIcon(this);" onmouseout="reIcon(this);" />
  11.  
  12.    <span>link7</span>
  13.   </a>
  14.  </li>
  15.  
  16.  
  17.  <li>
  18.   <a href="#">
  19.  
  20.    <img src="images/icon6.png" style="width:68px;height:68px;" onload="alphaPNG(this);" onmouseover="largeIcon(this);" onmouseout="reIcon(this);" />
  21.  
  22.    <span>link6</span>
  23.   </a>
  24.  </li>
  25.  
  26.  
  27.  </ul>
  28. </div>
  29.  
  30.  
  31. </div>

为了追求立体感,图标不能有背景色,所以必须用透明PNG图片,这里用<img>标签插入图片,是因为要实现图标的缩小放大效果(CSS背景里的图片只能控制位置,不能改变大小),图标的长宽要写在元素的style属性里,方便JS程序控制。

由于IE6不支持PNG的透明背景,必须用滤镜来做HACK才能达到一样的效果,而滤镜只能写在CSS的背景属性里…………为了解决这个矛盾,就要依靠JS了:

  1. function alphaPNG(png)
  2. {
  3. var aVersion=navigator.appVersion.split("MSIE");
  4.  
  5. var version=parseInt(aVersion[1]);
  6. var pp=png.parentNode;
  7.  
  8. if( (version>=5.5) && (version<7) && (document.body.filters) )
  9.  
  10. {
  11.  var mout=png.onmouseout.toString();
  12.  
  13.  var mover=png.onmouseover.toString();
  14.  
  15.  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+";\" onmouseover=\""+mover.substring(mover.indexOf("{")+1,mover.lastIndexOf("}"))+"\" onmouseout=\""+mout.substring(mout.indexOf("{")+1,mout.lastIndexOf("}"))+"\" ></span>";
  16.  
  17.  png.outerHTML=alphaHTML;
  18. }
  19.  
  20. }

这个函数已经写在图片的onload事件里了,会在IMG标签的内容加载完后触发(这个事件虽好,也不能到处乱用,根据伟大的犀牛书V5,onload只支持body, frameset, img),函数先判断浏览器类型和版本(IE7支持透明PNG),先创建一个span元素,IMG标签的所有属性、事件都原样COPY到SPAN上,而PNG图片则放到SPAN的背景里,用滤镜处理成透明,注意滤镜属性里必须要有sizingMethod=scale。最后用outerHTML(只有IE支持)把该IMG替换成span。

导航栏的样式:

  1. .iconbarout
  2. {
  3. width:770px;
  4.  
  5. position:absolute;
  6. top:40px;right:10px;
  7.  
  8. }
  9.  
  10. .iconbar{
  11. overflow:hidden;
  12. float:left;
  13.  
  14. }
  15.  
  16. .iconbar li{
  17. float:right;
  18. padding:0px;
  19.  
  20. width:auto;
  21. text-align:center;
  22. margin:0 16px 0 0px;
  23.  
  24. }
  25. .iconbar li span{
  26. color:#333;
  27. font-weight:600;
  28.  
  29. width:auto;
  30. display:block;
  31. float:none;
  32.  
  33. margin:0px auto;
  34. }
  35. .iconbar li a img{
  36. margin:0px auto;
  37.  
  38. float:none;
  39. }
  40. .iconbar li a{
  41. text-align:center;
  42.  
  43. float:none;
  44. margin:0px auto;
  45. }
  46. .iconbar li img{
  47.  
  48. border:0px;
  49. float:left;
  50. }

这样就在IE和Firefox里实现一样的视觉效果了(这里存在一个问题,为了保证图标放大后的清晰度,初始的图标都是缩小的,在IE7和Firefox里都会看到一点锯齿,而IE6由于用了滤镜,缩小的图标边缘仍然是平滑的-_____-b)

接下来做鼠标滑过的放大缩小效果。JS的动画效果一般是利用setTimeout或setInterval的延迟功能,反复循环来实现的。为了避免这些图标在运行函数时发生冲突,我把缩放的动画效果封装到了一个类里:

  1. /* zoom class by Dexter.Yy
  2. ********************************************************/
  3.  
  4. function animeZoom(ico,gWidth,gHeight,nWidth,nHeight)
  5.  
  6. {
  7. this.png=ico;
  8. this.iheight=nHeight;
  9.  
  10. this.iWidth=nWidth;
  11. this.goWidth=gWidth;
  12. this.goHeight=gHeight;
  13.  
  14. this.rico;
  15. }
  16.  
  17. animeZoom.prototype.zoomEvent=function()
  18.  
  19. {
  20. if(this.iWidth<this.goWidth)
  21. {
  22.  this.goEnlarge();
  23.  
  24. }
  25. else if(this.iWidth>this.goWidth)
  26. {
  27.  
  28.  this.goReduce();
  29. }
  30.  
  31. }
  32.  
  33. animeZoom.prototype.goEnlarge=function()
  34.  
  35. {
  36. this.png.style.width=this.goWidth+"px";
  37.  
  38. this.png.style.height=this.goWidth+"px";
  39.  
  40. }
  41.  
  42. animeZoom.prototype.goReduce=function()
  43. {
  44. var obj=this;
  45.  
  46. var h=parseInt(this.png.style.height);
  47.  
  48. var w=parseInt(this.png.style.width);
  49.  
  50. if(w>this.goWidth)
  51. {
  52.  this.png.style.width=w-2+"px";
  53.  
  54.  this.png.style.height=h-2+"px";
  55.  
  56.  this.rico=setTimeout(function(){obj.goReduce();},30);
  57.  
  58. }
  59. else
  60. {
  61.  window.clearTimeout(this.rico);
  62.  
  63. }
  64. }

使用时要传5个参数:目标对象、期望达到的宽度、期望达到的高度、原始宽度、原始高度,像这样:

  1. function largeIcon(png)
  2. {
  3. var lIco=new animeZoom(png,91,91,68,68);
  4.  
  5. lIco.zoomEvent();
  6. }
  7.  
  8. function reIcon(png)
  9.  
  10. {
  11. var rIco=new animeZoom(png,68,68,91,91);
  12.  
  13. rIco.zoomEvent();
  14. }

OK完工……如果是在FLASH里做这种推挤效果,可能还要写一大堆AS,但这里有CSS的浮动属性帮忙,就很省事……

posted in CSS, JavaScript, 界面 by Dexter.Yy

Follow comments via the RSS Feed | Leave a comment | Trackback URL

Leave Your Comment

YY in Limbo (混沌海狂想) © Dexter.Yy

Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution - NonCommercial - ShareAlike 3.0(署名-非商业性使用-相同方式共享).
Creative Commons License