上周五抽空实现了一下谷歌首页(其实是韩国google先搞的)的动画效果,感觉挺有意思,在这里和大家分享下。(文/
jinweijie)
这个效果的思路蛮有趣的,是一个类似于我们小时候翻书动画(也叫走马灯?)的效果,将一张大的png图片每次显示一部分。
说明一下,我的实现没有google的那样精致,它最后还有一个返回一点的效果。我为了简单,省略了,呵呵。
首先,这是google用的素材图片:
附件:
toolbar_animation_google.jpg 这是我的素材图片:
附件:
ani_my.jpg 区别就在于我把最后那条边裁了,就没有那一小点回退的效果了
然后是容器的css:
- <style type="text/css">
- .animator_containter{}{
- margin: 0.5em auto;
- background: transparent url(ani.png) no-repeat scroll 0px 0px ;
- width: 52px; /*每次显示部分png图片的宽度*/
- height: 37px; /*每次显示部分png图片的高度*/
- cursor: pointer;
- -moz-background-clip: -moz-initial;
- -moz-background-origin: -moz-initial;
- -moz-background-inline-policy: -moz-initial;
- }
- </style>
复制代码然后是namespace和常用方法:
- /**//**
- * @author wjjin
- */
- if (typeof(geekeesjs) == "undefined")
- _geekees = geekeesjs = {};
- function $() {
- var elements = new Array();
- for (var i = 0; i < arguments.length; i++) {
- var element = arguments;
- if (typeof element == 'string')
- element = document.getElementById(element);
- if (arguments.length == 1)
- return element;
- elements.push(element);
- }
- return elements;
- }
复制代码接着是一个Timer的类,用来在oo的编程方式下管理setTimeout和setInterval,这个类真的很实用,是偶尔发现的,出处忘了,对作者说个不好意思。
- //Updated 4/18/2003: Footprint decreased, minor code improvements.
- //Updated 5/3/2003: Minor comment clarification; no code changes.
- //Updated 5/10/2003: Minor code improvements.
- // The constructor should be called with
- // the parent object (optional, defaults to window).
- function Timer(){
- this.obj = (arguments.length)?arguments[0]:window;
- return this;
- }
- // The set functions should be called with:
- // - The name of the object method (as a string) (required)
- // - The millisecond delay (required)
- // - Any number of extra arguments, which will all be
- // passed to the method when it is evaluated.
- Timer.prototype.setInterval = function(func, msec){
- var i = Timer.getNew();
- var t = Timer.buildCall(this.obj, i, arguments);
- Timer.set.timer = window.setInterval(t,msec);
- return i;
- }
- Timer.prototype.setTimeout = function(func, msec){
- var i = Timer.getNew();
- Timer.buildCall(this.obj, i, arguments);
- Timer.set.timer = window.setTimeout("Timer.callOnce("+i+");",msec);
- return i;
- }
- // The clear functions should be called with
- // the return value from the equivalent set function.
- Timer.prototype.clearInterval = function(i){
- if(!Timer.set) return;
- window.clearInterval(Timer.set.timer);
- Timer.set = null;
- }
- Timer.prototype.clearTimeout = function(i){
- if(!Timer.set) return;
- window.clearTimeout(Timer.set.timer);
- Timer.set = null;
- }
- // Private data
- Timer.set = new Array();
- Timer.buildCall = function(obj, i, args){
- var t = "";
- Timer.set = new Array();
- if(obj != window){
- Timer.set.obj = obj;
- t = "Timer.set["+i+"].obj.";
- }
- t += args[0]+"(";
- if(args.length > 2){
- Timer.set[0] = args[2];
- t += "Timer.set["+i+"][0]";
- for(var j=1; (j+2)<args.length; j++){
- Timer.set[j] = args[j+2];
- t += ", Timer.set["+i+"]["+j+"]";
- }
- }
- t += ");";
- Timer.set.call = t;
- return t;
- }
- Timer.callOnce = function(i){
- if(!Timer.set) return;
- eval(Timer.set.call);
- Timer.set = null;
- }
- Timer.getNew = function(){
- var i = 0;
- while(Timer.set) i++;
- return i;
- }
复制代码准备工作做完,接下来开始代码主题了,其实还是挺简单的,递归调用而已,只不过是oo的方法实现,看起来比较那个,呵呵。注释是用英文写的,看懂应该问题不大。
- <script type="text/javascript">
- //***************************Class _geekees.Animator********************************
-
- //initialize
- if (typeof(_geekees.Animator) == "undefined")
- _geekees.Animator = {};
- else
- alert("Animator is already set!");
-
- //constructor
- _geekees.Animator = function( containerId
- , width
- , height
- , initialPosX
- , initialPosY
- , motionTime
- , stepX
- , stepY ){
-
- this.container = $( containerId );
- this.container.style.width = width + "px";
- this.container.style.height = height + "px";
- this.container.style.backgroundPosition = initialPosX + "px " + initialPosY + "px";
- this.startPosX = 0;
- this.startPosY = 0;
- this.endPosX = 0;
- this.endPosY = 0;
- this.isForwardX = true;
- this.isForwardY = true;
- this.motionTime = motionTime;
- this.timer = new Timer( this );//initial the Timer class
- this.stepX = stepX;//each time moving step
- this.stepY = stepY;
- }
-
- //move method
- _geekees.Animator.prototype.move = function(){
-
- if (this.isForwardX) {
- if (this.startPosX < this.endPosX) {
- this.timer.setTimeout('move', this.motionTime);
- this.startPosX += this.stepX;
- }
- }
- else {
- if (this.startPosX > this.endPosX) {
- this.timer.setTimeout('move', this.motionTime);
- this.startPosX -= this.stepX;
- }
- }
-
- if (this.isForwardY) {
- if (this.startPosY < this.endPosY) {
- this.timer.setTimeout('move', this.motionTime);
- this.startPosY += this.stepY;
- }
- }
- else {
- if (this.startPosY > this.endPosY) {
- this.timer.setTimeout('move', this.motionTime);
- this.startPosY -= this.stepY;
- }
- }
-
- //set the container status
- this.container.style.backgroundPosition = this.startPosX + "px " + this.startPosY + "px";
-
- }
-
- //the method which to be called
- _geekees.Animator.prototype.animate = function( startX, endX, startY, endY ){
- this.startPosX = startX;
- this.endPosX = endX;
- this.startPosY = startY;
- this.endPosY = endY;
-
- this.isForwardX = startX <= endX;//determine whether start position is larger than end position
- this.isForwardY = startY <= endY;
-
- this.move();
- }
- //***************************End of Class _geekees.Animator********************************
-
-
-
-
- /**//******************test*******************/
- function go(){
- ani.animate( 0, -208, 0, 0 );
- }
-
- function back(){
- ani.animate( -208, 0, 0, 0 );
- }
-
- var ani = new _geekees.Animator( 'divAni', 52, 37, 0, 0, 100 ,52, 0);
- </script>
复制代码最后是那个container,也就是一个div:
- <div id="divAni" class="animator_containter" onmouseover="go();return false;" onmouseout="back();return false;">
-
- </div>
复制代码完整代码下载: