上周五抽空实现了一下谷歌首页(其实是韩国google先搞的)的动画效果,感觉挺有意思,在这里和大家分享下。(文/jinweijie

这个效果的思路蛮有趣的,是一个类似于我们小时候翻书动画(也叫走马灯?)的效果,将一张大的png图片每次显示一部分。

说明一下,我的实现没有google的那样精致,它最后还有一个返回一点的效果。我为了简单,省略了,呵呵。

首先,这是google用的素材图片:
附件: toolbar_animation_google.jpg

这是我的素材图片:
附件: ani_my.jpg

区别就在于我把最后那条边裁了,就没有那一小点回退的效果了

然后是容器的css:
  1. <style type="text/css">
  2.         .animator_containter{}{
  3.             margin: 0.5em auto;
  4.             background: transparent url(ani.png) no-repeat scroll 0px 0px ;
  5.             width: 52px; /*每次显示部分png图片的宽度*/
  6.             height: 37px; /*每次显示部分png图片的高度*/
  7.             cursor: pointer;
  8.             -moz-background-clip: -moz-initial;
  9.             -moz-background-origin: -moz-initial;
  10.             -moz-background-inline-policy: -moz-initial;
  11.         }
  12.     </style>
复制代码
然后是namespace和常用方法:
  1. /**//**
  2. * @author wjjin
  3. */


  4. if (typeof(geekeesjs) == "undefined")
  5.             _geekees = geekeesjs = {};

  6. function $() {
  7.     var elements = new Array();
  8.     for (var i = 0; i < arguments.length; i++) {
  9.         var element = arguments;
  10.         if (typeof element == 'string')
  11.             element = document.getElementById(element);
  12.         if (arguments.length == 1)
  13.             return element;
  14.         elements.push(element);
  15.     }
  16.     return elements;
  17. }
复制代码
接着是一个Timer的类,用来在oo的编程方式下管理setTimeout和setInterval,这个类真的很实用,是偶尔发现的,出处忘了,对作者说个不好意思。
  1. //Updated 4/18/2003: Footprint decreased, minor code improvements.
  2. //Updated 5/3/2003: Minor comment clarification; no code changes.
  3. //Updated 5/10/2003: Minor code improvements.
  4. // The constructor should be called with
  5. // the parent object (optional, defaults to window).

  6. function Timer(){
  7.     this.obj = (arguments.length)?arguments[0]:window;
  8.     return this;
  9. }

  10. // The set functions should be called with:
  11. // - The name of the object method (as a string) (required)
  12. // - The millisecond delay (required)
  13. // - Any number of extra arguments, which will all be
  14. // passed to the method when it is evaluated.

  15. Timer.prototype.setInterval = function(func, msec){
  16.     var i = Timer.getNew();
  17.     var t = Timer.buildCall(this.obj, i, arguments);
  18.     Timer.set.timer = window.setInterval(t,msec);
  19.     return i;
  20.     }
  21.     Timer.prototype.setTimeout = function(func, msec){
  22.     var i = Timer.getNew();
  23.     Timer.buildCall(this.obj, i, arguments);
  24.     Timer.set.timer = window.setTimeout("Timer.callOnce("+i+");",msec);
  25.     return i;
  26. }

  27. // The clear functions should be called with
  28. // the return value from the equivalent set function.

  29. Timer.prototype.clearInterval = function(i){
  30.     if(!Timer.set) return;
  31.     window.clearInterval(Timer.set.timer);
  32.     Timer.set = null;
  33.     }
  34.     Timer.prototype.clearTimeout = function(i){
  35.     if(!Timer.set) return;
  36.     window.clearTimeout(Timer.set.timer);
  37.     Timer.set = null;
  38. }

  39. // Private data

  40. Timer.set = new Array();
  41. Timer.buildCall = function(obj, i, args){
  42.     var t = "";
  43.     Timer.set = new Array();
  44.     if(obj != window){
  45.         Timer.set.obj = obj;
  46.         t = "Timer.set["+i+"].obj.";
  47.     }
  48.     t += args[0]+"(";
  49.     if(args.length > 2){
  50.         Timer.set[0] = args[2];
  51.         t += "Timer.set["+i+"][0]";
  52.         for(var j=1; (j+2)<args.length; j++){
  53.             Timer.set[j] = args[j+2];
  54.             t += ", Timer.set["+i+"]["+j+"]";
  55.         }
  56.     }
  57.     t += ");";
  58.     Timer.set.call = t;
  59.     return t;
  60. }

  61. Timer.callOnce = function(i){
  62.     if(!Timer.set) return;
  63.     eval(Timer.set.call);
  64.     Timer.set = null;
  65. }
  66. Timer.getNew = function(){
  67.     var i = 0;
  68.     while(Timer.set) i++;
  69.     return i;
  70. }
复制代码
准备工作做完,接下来开始代码主题了,其实还是挺简单的,递归调用而已,只不过是oo的方法实现,看起来比较那个,呵呵。注释是用英文写的,看懂应该问题不大。
  1. <script type="text/javascript">
  2.         //***************************Class _geekees.Animator********************************
  3.        
  4.         //initialize
  5.         if (typeof(_geekees.Animator) == "undefined")
  6.             _geekees.Animator = {};
  7.         else
  8.             alert("Animator is already set!");
  9.    
  10.         //constructor
  11.         _geekees.Animator = function( containerId
  12.                                         , width
  13.                                         , height
  14.                                         , initialPosX
  15.                                         , initialPosY
  16.                                         , motionTime
  17.                                         , stepX
  18.                                         , stepY ){
  19.                    
  20.             this.container = $( containerId );
  21.             this.container.style.width = width + "px";
  22.             this.container.style.height = height + "px";
  23.             this.container.style.backgroundPosition = initialPosX + "px " + initialPosY + "px";
  24.             this.startPosX = 0;
  25.             this.startPosY = 0;
  26.             this.endPosX = 0;
  27.             this.endPosY = 0;
  28.             this.isForwardX = true;
  29.             this.isForwardY = true;
  30.             this.motionTime = motionTime;
  31.             this.timer = new Timer( this );//initial the Timer class
  32.             this.stepX = stepX;//each time moving step
  33.             this.stepY = stepY;
  34.         }
  35.        
  36.         //move method
  37.         _geekees.Animator.prototype.move = function(){
  38.            
  39.             if (this.isForwardX) {
  40.                 if (this.startPosX < this.endPosX) {
  41.                     this.timer.setTimeout('move', this.motionTime);
  42.                     this.startPosX += this.stepX;
  43.                 }
  44.             }
  45.             else {
  46.                 if (this.startPosX > this.endPosX) {
  47.                     this.timer.setTimeout('move', this.motionTime);
  48.                     this.startPosX -= this.stepX;
  49.                 }
  50.             }
  51.            
  52.             if (this.isForwardY) {
  53.                 if (this.startPosY < this.endPosY) {
  54.                     this.timer.setTimeout('move', this.motionTime);
  55.                     this.startPosY += this.stepY;
  56.                 }
  57.             }
  58.             else {
  59.                 if (this.startPosY > this.endPosY) {
  60.                     this.timer.setTimeout('move', this.motionTime);
  61.                     this.startPosY -= this.stepY;
  62.                 }
  63.             }
  64.            
  65.             //set the container status
  66.             this.container.style.backgroundPosition = this.startPosX + "px " + this.startPosY + "px";
  67.            
  68.         }
  69.        
  70.         //the method which to be called
  71.         _geekees.Animator.prototype.animate = function( startX, endX, startY, endY ){
  72.             this.startPosX = startX;
  73.             this.endPosX = endX;
  74.             this.startPosY = startY;
  75.             this.endPosY = endY;
  76.            
  77.             this.isForwardX = startX <= endX;//determine whether start position is larger than end position
  78.             this.isForwardY = startY <= endY;
  79.                        
  80.             this.move();
  81.         }
  82.         //***************************End of Class _geekees.Animator********************************
  83.        
  84.        
  85.        
  86.        
  87.         /**//******************test*******************/
  88.         function go(){
  89.             ani.animate( 0, -208, 0,  0 );
  90.         }
  91.        
  92.         function back(){
  93.             ani.animate( -208, 0,  0,  0 );
  94.         }
  95.        
  96.         var ani = new _geekees.Animator( 'divAni', 52, 37, 0, 0,  100 ,52, 0);
  97.     </script>
复制代码
最后是那个container,也就是一个div:
  1. <div id="divAni" class="animator_containter" onmouseover="go();return false;" onmouseout="back();return false;">
  2.        
  3. </div>
复制代码
完整代码下载:
TOP