jq动画分析
Posted qq281113270
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了jq动画分析相关的知识,希望对你有一定的参考价值。
<!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>
以上是关于jq动画分析的主要内容,如果未能解决你的问题,请参考以下文章