<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>无标题文档</title>
</head>

<style>


#box{
opacity:1;
position: relative;
top:100px;
left: 0px;
width:300px;
height:300px;
border:1px #ccc solid;
  
  }
#book{
opacity:1;
position:absolute;
top:100px;
left: 100px;
width:100px;
height:100px;
background: red; 
  }
  
  #book1{
opacity:1;
position:absolute;
top:220px;
left: 0px;
width:100px;
height:100px;
 background: red; 
  }
.line{
 
position:absolute;
top:0px;
left: 200px;
width:1px;
height:500px;
 background:#000;
    
    }
</style>
<!--<script src="../jquery-2.2.3.js"></script>-->
 <body>
<button id="one">jQuery动画的模拟实现:放大</button> 
<button id="two">jQuery动画的模拟实现:缩小</button>
 <div id="box"> 
  <div id="book" ></div>
 </div> 
<!-- <div id="book1" ></div>-->
<!-- <div class="line"></div>-->
<script  >
  /*在ie中 consloe.log 如果不在控制台的时候会报错, 调试的时候 按f12 控制台 即可*/

var book = document.getElementById('book');
var book1 = document.getElementById('book1');
var one = document.getElementById('one');
var two = document.getElementById('two');

/*var $book = $('#book');
var i = 10
while(i){
    $book.append("<li>11</li>")
    i--;
}*/


////////////
//创建动画缓动对象 //
////////////
 //生成属性对应的动画算法对象
    // tweens保存每一个属性对应的缓动控制对象
    //properties[k] 值
    // k 是建
    //animation 动画对象
    // 参数为:animation.tweens.push( new Tween(properties[k], k, animation) )
    //Tween 构造函数
    // this.elem 就是用户传进来的dom节点
    //this.prop    = prop; 对象的属性
    //this.easing  = "swing"; //动画缓动算法
    //this.end动画最终值
    //单位 this.unit    = "px"
    //Tween 函数是初始化构造函数
    
function Tween(value, prop, animation) {
    //初始化
    this.elem    = animation.elem;
    this.prop    = prop;
    this.easing  = "swing"; //动画缓动算法
    this.options = animation.options;
    //获取初始值,就是获取动画样式的值, this.get();  
    this.start   = this.now = this.get();
    //动画最终值,就是用户输入的值
    this.end     = value;
    //单位
    this.unit    = "px"
}
//获取动画样式
function getStyles(elem, attr) {
    //return elem.ownerDocument.defaultView.getComputedStyle(elem, null);
    
    if(elem.currentStyle) {
             // ie   //这样兼容性强
            //console.log('attr='+attr+'||elem.currentStyle[attr]='+elem.currentStyle[attr])  
             if(elem.currentStyle[attr]=='auto'){
                   elem.style[attr] = '0px';
                 }
              return elem.currentStyle[attr];
        } else { 
            //ff w3c.
          
             return getComputedStyle(elem,false)[attr];
         } 
};

//动画算法
function swing(p) {
    //p 是动画时间比 0 ~ 1
    //Math.cos(x)    x 的余弦值。返回的是 1.0 到 -1.0 之间的数;
    //(p * Math.PI) 是 0到3.14
    //(p * Math.PI)/2  是0到1.57
    //所以   Math.cos(p * Math.PI) / 2   值: 0.5 ~ -05
    //tmpe 值越大跑的越快 
    var tmpe = 0.5 - Math.cos(p * Math.PI) / 2; 
    // tmpe = Math.sin(p*Math.PI/2)
    // console.log('p * Math.PI='+Math.sin(p * Math.PI))
     //console.log('Math.sin(p * Math.PI)='+ Math.sin(p*Math.PI/2));
    // console.log('Math.cos(p * Math.PI) / 2='+ Math.cos(p * Math.PI) / 2)
     // console.log('tmpe='+tmpe)
    return tmpe
}


Tween.prototype = {
    //获取元素的当前属性
    get: function() {
        var computed = getStyles(this.elem, this.prop);
        //var ret = computed.getPropertyValue(this.prop) || computed[this.prop];
        //var ret = computed[this.prop];
        //获取样式的值
        //return parseFloat(ret);
        return parseFloat(computed);
    },
    //运行动画
    run:function(percent){
        //percent 动画时间比 0-1
        var eased;
        //根据缓动算法改变percent
        this.pos = eased = swing(percent);
        //获取具体的改变坐标值 this.now缓冲值
          
        //this.now  (等于结束动画位置 - 开始动画的位置)* 时间戳比例,时间戳比例是从0 ~ 1  this.start 是起始的位置
        this.now = (this.end - this.start) * eased + this.start;
        //console.log('this.now='+this.now)
         
        //console.log('this.prop='+this.prop+'||this.start='+this.start)
        //最终改变坐标
        //console.log('this.prop='+this.prop+'||this.now='+this.now)
        
        this.elem.style[this.prop] = this.now + "px";
        return this;
    }
}


////////
//动画类 //
////////
//动画对象  elem
 //properties 动画属性
 //options 动画时间  
function Animation(elem, properties, options){
      //检查动画是否在执行     
    if (Animation.timerId !=undefined && Animation.timerId) {
            return false;
        }
    //动画对象
    //animation.elem 动画对象
    //animation.props 动画属性
    //options.options 动画时间
    //Animation.fxNow || createFxNow() 开始动画的时间
    //tweens          : [] //存放每个属性的缓动对象,用于动画
    var animation = {
        elem            : elem,
        props           : properties,
        originalOptions : options,
        options         : options,
        startTime       : null,//动画开始时间
        tweens          : [] //存放每个属性的缓动对象,用于动画
    }

    //生成属性对应的动画算法对象
    // tweens保存每一个属性对应的缓动控制对象
    //properties[k] 值
    // k 是建
    //animation 动画对象
    for (var k in properties) {
     
        // tweens保存每一个属性对应的缓动控制对象
        animation.tweens.push( new Tween(properties[k], k, animation) )
    }

    //动画状态
    //var stopped;
    //把 animation.startTime=Animation.fxNow || createFxNow(); 放在这里 为了避免 for (var k in properties) for循环的时候如果属性多的时候会出现时间误差,虽然不是很大,但是如果属性很多的话就显得很明显
    animation.startTime=Animation.fxNow || createFxNow();
    //动画的定时器调用包装器  动画循环函数 tick 每13毫秒执行一次
    var tick = function() {
        // console.log(1)
        //如果 stopped 为真则 停止函数
        //if (stopped) {
        //    return false;
        //}
        
        //动画时间算法  每次更新动画的时间戳
        var currentTime = Animation.fxNow || createFxNow();
            //运动时间递减  
            remaining = Math.max(0, animation.startTime + animation.options.duration - currentTime),
            //时间比
            temp = remaining / animation.options.duration || 0,
            //取反时间比
            percent = 1 - temp;

        var index = 0,
            length = animation.tweens.length;

        //执行动画改变
        for (; index < length; index++) {
            //percent改变值
            //animation.tweens[index] 动画的对 象percent 动画时间比 0-1
            // run 就是一个动画执行多少个动画属性
            animation.tweens[index].run(percent);
        }

        //是否继续,还是停止动画  percent <= 1 表示动画已经到达位置了
        if (percent <= 1 && length) {
             
            return remaining;
            
        } else {
            //停止 动画
             
            return false;
        }

    }
    tick.elem = elem;
    tick.anim = animation;
   //只是调用一次而已
   //console.log(3333)
    Animation.fx.timer(tick);
}    

//创建 获取时间戳 函数
function createFxNow() {
    setTimeout(function() {
        //给 Animation.fxNow = undefined; 一个空的对象
        Animation.fxNow = undefined;
    });
    //Date.now() 时间戳
    return (Animation.fxNow = Date.now());
}


 

Animation.fx = {
    //开始动画队列  这个函数也是执行一次而已
    timer: function(timer) {
        
           //这里是把函数放到一个数组里面?有何用处
        Animation.timer=timer;
         
        if (timer()) {  //timer() 只是调用一个而已,就是说有这个动画时候就执行函数 返回一个false 或者是 remaining;
            //开始执行动画 走这里
            Animation.fx.start();
        }  
    },
    //开始循环 这个函数也是执行一次而已
    start: function() {
        if (!Animation.timerId) {
             
            Animation.timerId = setInterval(Animation.fx.tick, 13);
        }
    },
    //停止循环 停止定时器
    stop:function(){
        clearInterval(Animation.timerId);
        Animation.timerId = null;
        
    },
    //循环的的检测  重点是这里
    tick: function() {
         var timer,
            i = 0;
         //每次更新时间戳
         Animation.fxNow = Date.now();
         //console.log(1)
         //如果所有的动画都执行完了就停止这个定时器
        if (!Animation.timer()) {
            //console.log('Animation.timer()')
            //console.log(!Animation.timer())
            Animation.fx.stop();
         }
        //问题出在这里,因为当执行完只有 Animation.fxNow 时间戳变量值还在,所以就产生了bug
         Animation.fxNow = undefined;
    }
}





 one.onclick=function(){
     
    Animation(book, {
         'width': '300',
         'height':'300',
         'marginLeft':'-100',
         'marginTop':'-100'
    }, {
        duration: 1000
    })
    
    
    
     
    
} 

two.onclick=function() {
     
    Animation(book, {
        width: '100',
        height:'100',
        marginLeft:'0',
        marginTop:'0'
     }, {
        duration: 1000
    })
} 













 
</script>
</body>
</html>

 

posted on 2016-05-25 09:54  qq281113270  阅读(184)  评论(0编辑  收藏  举报