模拟jquery动画方法实现


<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<script src="jquery-1.8.3.js"></script>
<script>

jQuery.fn.extend({

/**
* 自定义动画方法
*/
myAnimate:function(opt,duration,easing,callback){

if(!opt || typeof opt!=='object') return;
//修正参数
if(typeof duration ==='function'){
callback=duration;
easing=null;
duration=null;
}else if(isNaN(duration)){
callback=easing;
easing=duration;
duration=null;
}else if(typeof easing ==='function'){
callback=easing;
easing=null;
}
if(!duration && duration!=0) duration=400;
var operate = jQuery.getAnimateOpt(duration, easing, callback);

this.queue(function(){
//此处this指的是jquery获取回来的集合中的当前js原始对象
var $elem=$(this);
//一个属性一个动画对象
jQuery.each(opt,function(name,val){
//转换为驼峰式css属性名
name=jQuery.camelCase(name);
//为属性创建动画对象
var fx=new jQuery.fx($elem,operate,name);
//放进全局timers
jQuery.timers.push(fx);
//计算属性的初始值与结束值
var start=parseFloat($elem.css(name))||0;
var end=parseFloat(val);
//执行动画对象
fx.custom(start,end);
});
});

return this;

}

});

jQuery.timers=[];
jQuery.timerId;

/**
* 动画方法的回调函数修正与参数封装
*/
jQuery.getAnimateOpt=function(duration, easing, callback){
var obj = {
"duration": duration,
"easing": easing
}
obj.callback = function(){
callback && callback();
this.dequeue();
}
return obj;
}

/**
* 动画对象
*/
jQuery.fx=function(elem,operate,name){
this.elem=elem;
this.operate=operate;
this.name=name;
this.finish=false;//标示动画是否已执行完毕
}
/**
* 动画对象执行入口
*/
jQuery.fx.prototype.custom=function(start,end){
this.startTime=new Date().getTime(); //代表该属性开始执行动画的时间,在step中做比较使用
this.start=start;
this.end=end;
if(!jQuery.timerId){
jQuery.timerId=setInterval(this.tick,13);
}
}
/**
* 动画对象轮询执行入口
*/
jQuery.fx.prototype.tick=function(){
var fx,i=0;
while((fx=jQuery.timers[i++])){
//step方法返回true表示该属性动画已执行完毕
if(fx.step()){
//在timers中移除当前动画对象
jQuery.timers.splice(i-1,1);
}
}
if(jQuery.timers.length==0){
clearInterval(jQuery.timerId);
jQuery.timerId=null;
}
}
/**
* 动画对象真正执行函数
*/
jQuery.fx.prototype.step=function(){
var n=new Date().getTime();
if(n>(this.startTime+this.operate.duration)){
//修正该属性的误差
this.update(this.end);
this.finish=true;
//判断属性所属元素的属性动画是否已执行完毕,如果是,则执行回调,dequeue下一个函数
var fx,ci,i=0,done=true;
while((fx=jQuery.timers[i++])){
if(fx.elem==this.elem && !fx.finish){
done=false;
}
}
if(done){
this.operate.callback.call(this.elem);
}
return true;
}else{
//计算属性当前值,默认使用swing算法(慢-快-慢)
var pos=(jQuery.easing[this.operate.easing] || jQuery.easing.swing)((n-this.startTime)/this.operate.duration);//计算比例
var val=this.start+pos*(this.end-this.start);
//更新元素
this.update(val);
return false;
}
}
/**
* 更新动画元素状态
*/
jQuery.fx.prototype.update=function(val){
//console.log(val);
this.elem.css(this.name,val);
}
/**
* 停止属性动画
*/
jQuery.fx.prototype.stop=function(){
var fx,i=0;
while((fx=jQuery.timers[i++])){
if(fx==this){
//在timers中移除当前动画对象
jQuery.timers.splice(i-1,1);
}
}
}


//测试!!
$(function(){
$('div#t01').myAnimate({'margin-left':600,'width':300},600,'linear').myAnimate({'opacity':.5},function(){alert('finish!')});
$('div#t02').myAnimate({'margin-left':600,'width':300},600);
});

</script>
</head>
<body>
<div id="t01" style="background-color:green;width:200px;height:200px;">001</div>
<div id="t02" style="background-color:gray;width:200px;height:200px;">002</div>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值