如何写一个通用的JavaScript效果库!(1/2)
如何写一个通用的JavaScript效果库!(1/2)
发布时间:2016-12-30 来源:查字典编辑
摘要:JavaScript的动态效果最基本的是动态改变大小,移动位置,改变透明度,改变颜色等等。而其他一些比较炫的效果无非是对这些最基本效果的组合...

JavaScript的动态效果最基本的是动态改变大小,移动位置,改变透明度,改变颜色等等。

而其他一些比较炫的效果无非是对这些最基本效果的组合和运用。

现在网上已经有很多很不错的优秀Javascript库或者效果库,我们是否有必要再造轮子呢?

放眼望去,YahooUI,基于Prototype的scriptaculous,Rico,JQuery,Dojo,还有很多很多。

这些库都带有很不错很优秀的动态效果。我们可以直接使用。

但是对于一些中小型项目来说,只是偶尔用到一两个特效,就没有必要引用整个框架,要知道

这些家伙体积都不小哦.prototype.js50K,scripttaculous的effects.js也有40-50kdojo,yui更大。

在大多数情况下我们需要一个小巧独立(300行代码以内),无侵入性的效果库。.即使有现有的轮子,

我们不但要学会怎么使用轮子,更要学会如何亲手造一个轮子。

基于以上原因,我们今天来重写一个灵活的,扩展性强的,小巧的,跨浏览器的动态效果库。

考虑到prototype.js用户群的广泛性,我的部分代码引用了prototype.js,当然,我说过,我们要做一个独立

的效果库,即使在没有prototype.js的情况下,也要让代码正常工作。

先做一些准备工作。下面这些代码是任何效果库中必不可少的,因为它负责一些类似取位置坐标,

设置,获取element的透明度等这些基础工作。

代码:

复制代码 代码如下:

/*

这个函数的代码来自Prototype.jshttp://prototype.conio.net/

如果页面引用了prototype.js,则可以删除下面这个函数,

当然,即使不删除也没关系,因为作了简单的兼容性判断

*/

(function(){

if(!("Prototype"inwindow)){

Prototype={emptyFunction:function(){}};

Class={

create:function(){returnfunction(){this.initialize.apply(this,arguments)}}

};

$=function(element){

returntypeof(element)=="string"?document.getElementById(element):element

};

$A=function(arrLike){

for(vari=0,ret=[];i<arrLike.length;i++)ret[i]=arrLike[i];

returnret

};

Number.prototype.toColorPart=function(){returnString("00"+this.toString(16)).slice(-2)};

Function.prototype.bind=function(){

var__method=this,args=$A(arguments),object=args.shift();

returnfunction(){return__method.apply(object,args.concat($A(arguments)))}

}

Position={

cumulativeOffset:function(element){

varvalueT=0,valueL=0;

do{

valueT+=element.offsetTop||0;

valueL+=element.offsetLeft||0;

element=element.offsetParent;

}while(element);

return[valueL,valueT];

}

}

}

})()

/*

1.读取/设置透明度,

2.如果只传了一个参数element,则返回element的透明度(0<value<1)

3.如果传了两个参数element和value则把element的透明度设置为valuevalue范围0-1

*/

functionOpacity(element,value){

//byGo_Rush(阿舜)fromhttp://ashun.cnblogs.com/

varret;

if(value===undefined){//读取

if(!/msie/i.test(navigator.userAgent))

if(ret=element.style.opacity)returnparseFloat(ret);

try{returnelement.filters.item('alpha').opacity/100}catch(x){return1.0}

}else{//设置

value=Math.min(Math.max(value,0.00001),0.999999)//这句修复一些非ie浏览器opacity不能设置为1的bug

if(/msie/i.test(navigator.userAgent))returnelement.style.filter="alpha(opacity="+value*100+")"

returnelement.style.opacity=value

}

}

那么怎么设计这个Effect效果库呢。

首先,它的入口应该简洁。

1.一个是要使用效果的元素element

2.另一个是将要使用什么效果options

options应该是扩展性强的,方便用户使用的。我们把它设计成哈稀结构。

比如options={x:100,y:100}表示将element移动到坐标100,100

options={w:200,h:200}表示将element的大小改变为width=200,height=200

他们可以重叠,也可以确省比如options={h:20,y:20}这表示将element移动到top=20的位置,而且在移动的过程中让他的大小改变为height=20,同时,原来的left坐标和宽度都不发生改变,这是不是在做QQ的滑动效果呢?

还有控制效果的几个关键因素duration(整个效果的时间),delay(延迟几秒才开始效果),fps(频率快慢)都通过options传进来

复制代码 代码如下:

Effect=Class.create();

Effect.Fn=newObject();

Effect.Init=newObject();

//ByGo_Rush(阿舜)fromhttp://ashun.cnblogs.com/

Effect.prototype={

initialize:function(element,options){

this.element=$(element);

this.options=options||{};

this.duration=(this.options.duration||2)*1000;//效果执行时间

this.fps=this.options.fps||40;//频率

//当前步长,注:这个变量是递减的,当它0的时候意味着整个效果结束

this.steps=Math.floor(this.duration/this.fps);

this.maxSteps=this.steps;//整个效果的步长

this.setting=newObject();

this.timer=null;

if(this.options.delay){//延时处理

var_this=this;

setTimeout(function(){

_this.setup(_this);

(_this.options.onStart||Prototype.emptyFunction)(_this);

_this.run();

},_this.options.delay*1000);

}else{

this.setup(this);

(this.options.onStart||Prototype.emptyFunction)(this);

this.run();

}

},

run:function(){

if(this.isFinished())return(this.options.onComplete||Prototype.emptyFunction)(this);

if(this.timer)clearTimeout(this.timer);

this.duration-=this.fps;

this.steps--;

varpos=1-this.steps/this.maxSteps;//总进度的百分比

this.loop(this,pos);

(this.options.onUpdate||Prototype.emptyFunction)(this,pos);

this.timer=setTimeout(this.run.bind(this),this.fps);

},

isFinished:function(){

returnthis.steps<=0;

},

setup:function(effect){//初始化设置所有效果单元

for(varkeyinEffect.Init){

if(typeof(Effect.Init[key])!="function")continue;

try{Effect.Init[key](this)}catch(x){}

}

},

loop:function(effect,pos){//执行所有效果单元

for(varkeyinEffect.Fn){

if(typeof(Effect.Fn[key])!="function")continue;

try{Effect.Fn[key](effect,pos)}catch(x){}

}

}

}

当动态效果改变的时候,比如淡出,我们让一个element慢慢的变淡变小,并消失。

在不用效果库的情况下只用element.style.display="none"就做到了。

用效果库后,element.style的透明度opacity,尺寸width,height甚至位置left,top都发生了改变。

直到element的大小改变为0或者opactiy为0的时候他才会消失display="none"

那么,当下次再让他出现的时候,怎么恢复他的原始信息呢。比如width.height,opacity等。

在上面的代码中我们用effect.setting保存效果发生前的所有element信息.

注意以上三个自定义函数onStart,onUpdate,onComplete他们都是通过options传进来的调用者自定义函数。

分别在效果发生以前,效果发生时,效果发生完毕后执行。传入的参数可以查阅effect的所有对象。

看到这里,细心的看官可能注意到,这个效果库实际上什么效果都没有做,他只是搭了一个空架子。

Effect.Init给我们留了一个空接口供setup方法调用,Effect.Fn也是一个空接口供loop方法调用。

下面我们要做的是扩展Effect.Init和Effect.Fn来充实效果库。

先来一个大家最熟悉的淡入淡出

Effect.Init里面的所有成员函数都会被effect.setup执行,这个执行动作在效果开始之前,因此这里

适合做一些初始化的动作。比如把一些初始信息保存到effect.setting里面供以后使用。

Effect.Fn里面的所有成员函数都会被effect.loop执行,这个执行动作在效果运行中,因此这里

就要放核心效果代码,比如计算,改变效果增量等等。

复制代码 代码如下:

if(effect.options.opacity===undefined)return;

effect.setting.opacity=Opacity(effect.element);

}

Effect.Fn.opacity=function(effect,pos){

if(effect.options.opacity===undefined)return;

Opacity(effect.element,effect.setting.opacity+(effect.options.opacity-effect.setting.opacity)*pos);

}

下面贴出可调试代码(空效果库和淡入浅出插件):(可以拷贝到一个html运行,测试)

/**//* 这个函数的代码来自 Prototype.js http://prototype.conio.net/ 如果页面引用了prototype.js ,则可以删除下面这个函数, 当然,即使不删除也没关系,因为作了简单的兼容性判断 */ (function(){ if (!("Prototype" in window)){ Prototype={emptyFunction:function(){}}; Class ={ create: function(){return function(){this.initialize.apply(this, arguments)}} }; $ = function(element){ return typeof(element)=="string"?document.getElementById(element):element }; $A= function(arrLike){ for(var i=0,ret=[];i

推荐文章
猜你喜欢
附近的人在看
推荐阅读
拓展阅读
相关阅读
网友关注
最新Javascript教程学习
热门Javascript教程学习
编程开发子分类