上周五抽空实现了一下谷歌首页(其实是韩国google先搞的)的动画效果,感觉挺有意思,在这里和大家分享下。
这个效果的思路蛮有趣的,是一个类似于我们小时候翻书动画(也叫走马灯?)的效果,将一张大的png图片每次显示一部分。
说明一下,我的实现没有google的那样精致,它最后还有一个返回一点的效果。我为了简单,省略了,呵呵。
首先,这是google用的素材图片:
这是我的素材图片:
区别就在于我把最后那条边裁了,就没有那一小点回退的效果了
然后是容器的css:
<
style
type
="text/css"
>
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
.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
*/
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
if
(
typeof
(geekeesjs)
==
"
#ff0000
"
)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
_geekees
=
geekeesjs
=
{}
;
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
function
$()
{
var elements = new Array();
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for (var i = 0; i < arguments.length; i++)
{
var element = arguments[i];
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).
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
function
Timer()
{
this.obj = (arguments.length)?arguments[0]:window;
return this;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//
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.
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.prototype.setInterval
=
function
(func, msec)
{
var i = Timer.getNew();
var t = Timer.buildCall(this.obj, i, arguments);
Timer.set[i].timer = window.setInterval(t,msec);
return i;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.prototype.setTimeout
=
function
(func, msec)
{
var i = Timer.getNew();
Timer.buildCall(this.obj, i, arguments);
Timer.set[i].timer = window.setTimeout("Timer.callOnce("+i+");",msec);
return i;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//
The clear functions should be called with
//
the return value from the equivalent set function.
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.prototype.clearInterval
=
function
(i)
{
if(!Timer.set[i]) return;
window.clearInterval(Timer.set[i].timer);
Timer.set[i] = null;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.prototype.clearTimeout
=
function
(i)
{
if(!Timer.set[i]) return;
window.clearTimeout(Timer.set[i].timer);
Timer.set[i] = null;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
//
Private data
Timer.set
=
new
Array();
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.buildCall
=
function
(obj, i, args)
{
var t = "";
Timer.set[i] = new Array();
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(obj != window)
{
Timer.set[i].obj = obj;
t = "Timer.set["+i+"].obj.";
}
t += args[0]+"(";
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if(args.length > 2)
{
Timer.set[i][0] = args[2];
t += "Timer.set["+i+"][0]";
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
for(var j=1; (j+2)<args.length; j++)
{
Timer.set[i][j] = args[j+2];
t += ", Timer.set["+i+"]["+j+"]";
}
}
t += ");";
Timer.set[i].call = t;
return t;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.callOnce
=
function
(i)
{
if(!Timer.set[i]) return;
eval(Timer.set[i].call);
Timer.set[i] = null;
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
Timer.getNew
=
function
()
{
var i = 0;
while(Timer.set[i]) i++;
return i;
}
准备工作做完,接下来开始代码主题了,其实还是挺简单的,递归调用而已,只不过是oo的方法实现,看起来比较那个,呵呵。注释是用英文写的,看懂应该问题不大。
<
script
type
="text/javascript"
>
//***************************Class _geekees.Animator********************************
//initialize
if (typeof(_geekees.Animator) == "#ff0000")
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_geekees.Animator =
{};
else
alert("Animator is already set!");
//constructor
_geekees.Animator = function( containerId
, width
, height
, initialPosX
, initialPosY
, motionTime
, stepX
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
, 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
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_geekees.Animator.prototype.move = function()
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (this.isForwardX)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (this.startPosX < this.endPosX)
{
this.timer.setTimeout('move', this.motionTime);
this.startPosX += this.stepX;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
else
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (this.startPosX > this.endPosX)
{
this.timer.setTimeout('move', this.motionTime);
this.startPosX -= this.stepX;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (this.isForwardY)
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
if (this.startPosY < this.endPosY)
{
this.timer.setTimeout('move', this.motionTime);
this.startPosY += this.stepY;
}
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
else
{
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
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
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
_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********************************
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//******************test*******************/
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
function go()
{
ani.animate( 0, -208, 0, 0 );
}
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
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
>
完整代码下载
http://files.cnblogs.com/jinweijie/google_toolbar_ani.rar
【updated】
多个动画同时显示的调用
http://files.cnblogs.com/jinweijie/g_toolbar_multi.rar