前言
现在非常佩服
Google
的工程师,他们的程序开发技巧和考虑问题的深度确实很强。在下面的程序中,他们分析了
MAC
界面,然后分析了其中可能涉及到各个环节,然后使用
Javascript
来完成了相同的工作。尤其让我佩服得就是为了完成同样的效果,他们确实考虑了很多方法(比如微调步长,根据时间差来调整等等,持续重绘等等)。这段代码体现出了
google
工程师创新的思维和精益求精的态度,当然还有他们高超的程序撰写技巧。
正文
从
Tin
的个人主页那里看到的这个导航栏,
Tin
说这个来源于
Google
,他把相关的代码挑了出来,用在了自己的网页中。
我也觉得这个很有意思,它实现了类似
Mac
的风格。于是班门弄斧一下,分析了一下代码。
这里是源代码,
Google
似乎对变量的名字进行过了混淆。
<
SCRIPT
type
=text/javascript>
k=document;
v=Date;
x=false;
z=Array;
af=Math.floor;
ag=RegExp;
b=new z(11);
s=new z("null","home","hard","art","stamp","music","friend","love","me","guest","space");
aa=new z(11);
ab=10;
t=0;
u=0;
n=0;
o=new v();
h=5;
m=385;
c=0;
w=x;
var firstHoverOccurred=x;
m=385;
p=0;
// mouseover
事件处理程序
function d(ac){
c=ac;
o=new v();
setTimeout("gidle()",20);
}
// mouseout
事件处理程序
function e(ac){
c=0;
w=x;
o=new v();
setTimeout("gidle()",20);
}
// onload
的事件处理程序
function ae(){
for(var j=1;
j<b.length;
j++){
b[j]=35
}
for(i=0;
i<b.length;
i++){
aa[i]=new Image();
aa[i].src="images/icon/"+s[i+1]+".gif"
}
setTimeout("gidle()",20);
}
//
用于显示的函数,核心
function gidle(){
var l=0;
for(var i=1;i<b.length;i++){
var imagename="image"+i;
var imageElem=k.getElementById(imagename);
if(c!=i){
if(b[i]>35){
b[i]-=h;
if(b[i]<=35){
b[i]=35;
imageElem.src="images/icon/"+s[i]+"-sm.gif"
}
imageElem.width=b[i];
imageElem.height=b[i];
p=1
}
l+=b[i]
}
}
if(c!=0&&b[c]<80){
imagename="image"+c;
imageElem=k.getElementById(imagename);
b[c]+=h;
p=1;
if(b[c]>80){
b[c]=80
}
l+=b[c];
if(l<m){
b[c]+=m-l;
if(b[c]>80){
b[c]=80
}
l=m
}
imageElem.width=b[c];
imageElem.height=b[c];
k.getElementById(imagename).src="images/icon/"+s[c]+".gif"
}
m=l;
var ad=new v();
ab=ad.getTime()-o.getTime();
o=ad;
t+=ab;
u++;
n=t/u;
h=5;
if(u>4){if(n>30){
h=10
}
if(n>60){
h=15
}
if(n>90){
h=20
}
}
if(p){
setTimeout("gidle()",40);
p=0
}
}
</
SCRIPT
>
Google
的代码看起来很简单,就是把这些图标在网页上排列成一排,每一个图标都进行索引标记,当选择到这个图标的时候,这个图标就会放大。而没有被选择的图标会恢复原样。
但是这个过程并不是像上面描述的这样简单,当我们编写程序完成上述的简单想法的时候,例如如下的代码:
<
SCRIPT
type
=text/javascript>
number = 11;
mydocumentType=document;
myDateType=Date;
mydelay=20;
myArrayType=Array;
wide=new myArrayType(number);
imageArray=new myArrayType(number);
myDateTypeInstance=new myDateType();
currentIndex=0;
totolTime=0;
counter=0;
everageChangeTime=0;
contents=new myArrayType("null","home","hard","art","stamp","music","friend","love","me","guest","space");
function enter(current){
currentIndex=current;
myDateTypeInstance=new myDateType();
setTimeout("paint()",mydelay);
}
function exit(current){
currentIndex=0;
myDateTypeInstance=new myDateType();
setTimeout("paint()",mydelay);
}
function init(){
for(var j=1;j<wide.length;j++){
wide[j]=35
}
for(i=0;i<wide.length;i++){
imageArray[i]=new Image();
imageArray[i].src="images/"+contents[i+1]+".gif"
}
currentIndex = 0;
setTimeout("paint()",mydelay);
}
function paint(){
var totolWide=0;
//
用于调整非选择项的大小
for(var i=1;i<wide.length; i++){
var imagename="image"+i;
var imageElem=mydocumentType.getElementById(imagename);
if(currentIndex!=i){
wide[i]=35;
imageElem.src="images/"+contents[i]+"-sm.gif"
imageElem.width=wide[i];
imageElem.height=wide[i];
}
}
if(currentIndex!=0&&wide[currentIndex]<80){
imagename="image"+currentIndex;
imageElem=mydocumentType.getElementById(imagename);
wide[currentIndex]=80
imageElem.width=wide[currentIndex];
imageElem.height=wide[currentIndex]; mydocumentType.getElementById(imagename).src="images/"+contents[currentIndex]+".gif" }
}
</
SCRIPT
>
这个代码的效果就不是很好,如何能够达到真正的Mac的效果呢?关键就是模拟出那种过程。这也是Google
程序的重点,它通过不断地重绘来完成这种过程。
下面详细介绍Google程序的思路,整个程序分为三个部分
1,
微调没有被索引的图象的大小。
a)
如果这个图像没有被索引,那么这个图像应该是标准尺寸。
b)
所以需要考虑这个图像的大小,如果这个图像大小是标准尺寸,那么就没有任何问题
c)
如果这个图像经过减去步长值之后,还是没有达到标准尺寸,那么需要记录一下,保证能够进行重新绘制
2,
微调被索引的图象的大小
a)
将这个被索引的图象的宽度和步长相加
b)
如果新的宽度已经达到了最大尺寸,那么就没有任何问题
c)
如果没有达到的话,那么就需要进行记录,保证进行重新绘制
3,
计时,根据时间差调整步长
a)
Google
进行计时,我想主要的目的就是希望能够达到不同的效果:鼠标从图标栏上扫过和普通的把鼠标移动到某一个图标上并且不再继续移动这两种效果的不同。
b)
但是在代码里面,时间仅仅进行了一次初始化,没有进行更多的对这两种情况的判断,然后就简简单单的根据平均时间来进行步长的调整,我认为这种算法有些不是很周全。
4,
重新绘制
a)
重新进行绘制
下面是我自己修改的代码,去掉了时间的计算,在效果上基本上能够达到一致。
<
SCRIPT
type
="text/javascript">
number = 11; //
导航栏有多少项
mydocumentType=document; //
当前的文档对象
myDateType=Date; //
时间对象
mydelay=20; //
时间延迟
myArrayType=Array; //
数组对象
wide=new myArrayType(number); //
代表了每一个图标的宽度
imageArray=new myArrayType(number); //
代表了每一个Image对象
currentIndex=0; //
当前的索引
contents=new myArrayType("null","home","hard","art","stamp","music","friend","love","me","guest","space");
h=5; //
每次微调的步长
m=385; //
上次的大小
function enter(current){
currentIndex=current;
myDateTypeInstance=new myDateType();
setTimeout("paint()",mydelay);
}
function exit(current){
currentIndex=0;
myDateTypeInstance=new myDateType();
setTimeout("paint()",mydelay);
}
function init(){
for(var j=1;j<wide.length;j++){
wide[j]=35
}
for(i=0;i<wide.length;i++){
imageArray[i]=new Image();
imageArray[i].src="images/"+contents[i+1]+".gif"
}
currentIndex = 0;
setTimeout("paint()",mydelay);
}
//20
或者40 是一个极短的时间,用于进行微调
function paint(){
var totolWide =0;
var flag = 0;
//
用于调整非选择项的大小
for(var i=1;i<wide.length; i++){
var imagename="image"+i;
var imageElem=mydocumentType.getElementById(imagename); //
得到对应的Image元素
//
对于每一个非选择项,也许大家的大小都不同,但是需要逐步的调整小,直到恢复到正常的状况
if(currentIndex!=i){
//
如果已经<35了,那么就不用处理了.
if (wide[i]<=35)
{
wide[i]=35;
imageElem.src="images/"+contents[i]+"-sm.gif"
}
//
如果这个比大,而且已经焦点不在这个上面了,所以需要调整变小
if (wide[i]>35){
wide[i]-=h;
if (wide[i]<=35)
{
wide[i]=35;
imageElem.src="images/"+contents[i]+"-sm.gif"
}
else
{
//
表示需要不断的调整
flag =1;
}
imageElem.width=wide[i];
imageElem.height=wide[i];
}
//
记录一下总长度
totolWide+=wide[i];
}
}
//
调整被选择项的大小
if(currentIndex!=0&&wide[currentIndex]<=80){
imagename="image"+currentIndex;
imageElem=mydocumentType.getElementById(imagename);
wide[currentIndex]+=h;
if (wide[currentIndex] > 80){
wide[currentIndex]=80
}
else{
flag = 1;
}
//
保持整体的平衡
totolWide+=wide[currentIndex];
if(totolWide<m){
wide[currentIndex]+=m-totolWide;
if(wide[currentIndex]>80){
wide[currentIndex]=80
}
totolWide=m
}
imageElem.width=wide[currentIndex];
imageElem.height=wide[currentIndex];
mydocumentType.getElementById(imagename).src="images/"+contents[currentIndex]+".gif"
}
m=totolWide;
if (flag ==1)
{
setTimeout("paint()",mydelay*2);
}
}
</
SCRIPT
>
posted on 2006-06-05 15:55
豆之荚 阅读(264)
评论(0) 编辑 收藏