扩展$.animate
当前jquery提供了animate({key:value})形式的动画,但这个函数只能用于简单的“数字+单位”
(10px)。像样式background-position:10% 10%,transform都不支持。所以我们要写入自己的动画插件来扩展它。
1.以扩展background-position为例 ,首先我们要在$.Tween.propHooks插入对应的属性:
(function($){
$.Tween.propHooks['backgroundPosition']={
set:function(tween){
}
};
}(jQuery));
2.$.Tween.propHooks['backgroundPosition']
里面包含两个函数,set和get函数,我们的动画每次调用时都不断的循环set函数来更新样式的值:
(function($){
$.Tween.propHooks['backgroundPosition']={
set:function(tween){
//保证初始化设置一次初始,末尾属性值
if(!tween.set){
initBackgroundPosition(tween);
}
//设置样式:
//公式:pos*(end-start)+start
//pos为一个在0~1的时间相关的比值
$(tween.elem).css('background-position',
(tween.pos*(tween.end[0][1]-tween.start[0][1])+tween.start[0][1]*1)+tween.end[0][2]
+' '+
(tween.pos*(tween.end[1][1]-tween.start[1][1])+tween.start[1][1]*1)+tween.end[1][2]);
}
};
/*用来初始化样式属性的开始值与末尾值
设置解析后的tween.end,tween.start
*/
function initBackgroundPosition(tween){
tween.start=parseBackgroundPosition($(tween.elem).css("background-position"));
tween.end=parseBackgroundPosition(tween.end);
for(var i=0;i<tween.end.length;i++){
if(tween.end[i][0]){
tween.end[i][1]=tween.start[i][1]+(tween.end[i][0]=='-='? -1:+1)*tween.end[i][1];
}
}
tween.set=true;
}
/*解析样式的属性值*/
/*
情况一:"left right"
情况二:"30% 50%"
情况三:"-+50px +=50px"
思路:我们可以两个参数分开,并且每个参数分成三个部分来判断
例如["-=","50","px"] ["undefined","50","%"]
@param {string} value 属性值
@return {array} bogPos 包含两个值的数组,每个值又是一个数组
*/
function parseBackgroundPosition(value){
var bgPos=value.split(' ');
var posStr={left:"0%",center:"50%",right:"100%",top:"0%",bottom:"100%"};
var decodeBgPos=function(index){
var posArr=(posStr[index]? posStr:bgPos[index]).match(/^([+-]=)?([+-]?\d+)(\.\d+)?(.*)?$/);
return [posArr[1],posArr[2],posArr[4]||"px"];
};
bgPos[0]=decodeBgPos(0);
bgPos[1]=decodeBgPos(1);
return bgPos;
}
}(jQuery));
扩张缓动动画
缓动: 一个属性的变化速度是随着时间变化的,它是非线性的。
一个缓动被实现为一个函数,它返回一个给定时间的属性值。为了迎合用户自定义动画的时长和属性范围的需求,这个函数被标准化为接收一个介于0.0-1.0之间的时间,并且产生的返回值也介于0.0-1.0之间。
例如下面的swing缓动函数:
jQuery.easing={
/*新版本
*@param p:到1的一个很时间成正比的数
*@return 一个和曲线y轴成正比的0-1之间的书
*/
swing:function(p){
return 0.5-Math.cos(p*Math.PI)/2;
}
//旧版本
/*
* t: current time(当前时间)
* b: beginning value(初始值,默认为0)
* c: change in value(变化量,默认为1)
* d: duration(持续时间)
*/
swing:function(p,t,b,c,d){
return c*(0.5-Math.cos(t/d*Math.PI)/2)*b;
}
}