在页面中实现运动的四种方式
1.速度版:
1 function startMove(obj,json,fnEnd){ 2 if(obj.timer){ 3 clearInterval(obj.timer); 4 } 5 obj.timer = setInterval(function(){ 6 doMove(obj,json,fnEnd); 7 },30); 8 } 9 function doMove(obj,json,fnEnd){ 10 var iCur = 0; 11 var attr = null; 12 var bStop = true; 13 for(attr in json){ 14 if(attr=='opacity'){ 15 iCur = parseInt(100*parseFloat(getStyle(obj,attr))); 16 } 17 else{ 18 iCur = parseInt(getStyle(obj,attr)); 19 } 20 var iSpeed = (json[attr] - iCur)/8; 21 iSpeed = iSpeed>0 ? Math.ceil(iSpeed) : Math.floor(iSpeed); 22 if(json[attr]!=iCur){ 23 bStop = false; 24 } 25 if(attr=='opacity'){ 26 obj.style.filter = 'alpha(opacity='+ (iCur + iSpeed) +')'; 27 obj.style.opacity = (iCur + iSpeed)/100; 28 } 29 else{ 30 obj.style[attr] = iCur + iSpeed + 'px'; 31 } 32 } 33 if(bStop){ 34 clearInterval(obj.timer); 35 obj.timer = null; 36 if(fnEnd){ 37 fnEnd(); 38 } 39 } 40 } 41 function getStyle(obj,attr){ 42 if(obj.currentStyle){ 43 return obj.currentStyle[attr]; 44 } 45 else{ 46 return getComputedStyle(obj)[attr]; 47 } 48 }
速度版运动框架有个小问题,不是代码的问题,而是浏览器本身的功能问题。当运动途中,切换页面或缩小浏览器窗口后,浏览器会自动放慢页面中所有的定时器,这样可能会导致页面中的定时器出问题:比如有的定时器有回调函数,有的定时器没有,当重新切换回原来的页面时,有回调函数的定时器可能回调会来不及执行,造成页面中定时器的混乱状态,影响页面的效果。如果是一个简单的轮播图效果,我们可以使用如下代码简单处理下:
1 window.onfocus = function(){ 2 console.log(1); 3 timer = setInterval(toRun,2000); 4 }; 5 6 window.onblur = function(){ 7 console.log(2); 8 clearInterval(timer); 9 };
2.时间版:
1 function startMove(obj,json,times,fx,fn){ 2 3 if( typeof times == 'undefined' ){ 4 times = 400; 5 fx = 'linear'; 6 } 7 8 if( typeof times == 'string' ){ 9 if(typeof fx == 'function'){ 10 fn = fx; 11 } 12 fx = times; 13 times = 400; 14 } 15 else if(typeof times == 'function'){ 16 fn = times; 17 times = 400; 18 fx = 'linear'; 19 } 20 else if(typeof times == 'number'){ 21 if(typeof fx == 'function'){ 22 fn = fx; 23 fx = 'linear'; 24 } 25 else if(typeof fx == 'undefined'){ 26 fx = 'linear'; 27 } 28 } 29 30 var iCur = {}; 31 for(var attr in json){ 32 iCur[attr] = 0; 33 attr == 'opacity' ? iCur[attr] = Math.round(getStyle(obj,attr)*100) : iCur[attr] = parseInt(getStyle(obj,attr)); 34 } 35 36 var startTime = now(); 37 clearInterval(obj.timer); 38 39 obj.timer = setInterval(function(){ 40 41 var changeTime = now(); 42 var t = times - Math.max(0,startTime - changeTime + times); 43 44 for(var attr in json){ 45 46 var value = Tween[fx](t,iCur[attr],json[attr]-iCur[attr],times); 47 48 if(attr == 'opacity'){ 49 obj.style.opacity = value/100; 50 obj.style.filter = 'alpha(opacity='+value+')'; 51 } 52 else{ 53 obj.style[attr] = value + 'px'; 54 } 55 56 } 57 58 if(t == times){ 59 clearInterval(obj.timer); 60 fn && fn.call(obj); 61 } 62 63 },20); 64 65 function getStyle(obj,attr){ return obj.currentStyle ? obj.currentStyle[attr] : getComputedStyle(obj,false)[attr]; } 66 function now(){ return (new Date()).getTime(); } 67 }; 68 69 var Tween = { 70 linear: function (t, b, c, d){ //匀速 71 return c*t/d + b; 72 }, 73 easeIn: function(t, b, c, d){ //加速曲线 74 return c*(t/=d)*t + b; 75 }, 76 easeOut: function(t, b, c, d){ //减速曲线 77 return -c *(t/=d)*(t-2) + b; 78 }, 79 easeBoth: function(t, b, c, d){ //加速减速曲线 80 if ((t/=d/2) < 1) { 81 return c/2*t*t + b; 82 } 83 return -c/2 * ((--t)*(t-2) - 1) + b; 84 }, 85 easeInStrong: function(t, b, c, d){ //加加速曲线 86 return c*(t/=d)*t*t*t + b; 87 }, 88 easeOutStrong: function(t, b, c, d){ //减减速曲线 89 return -c * ((t=t/d-1)*t*t*t - 1) + b; 90 }, 91 easeBothStrong: function(t, b, c, d){ //加加速减减速曲线 92 if ((t/=d/2) < 1) { 93 return c/2*t*t*t*t + b; 94 } 95 return -c/2 * ((t-=2)*t*t*t - 2) + b; 96 }, 97 elasticIn: function(t, b, c, d, a, p){ //正弦衰减曲线(弹动渐入) 98 if (t === 0) { 99 return b; 100 } 101 if ( (t /= d) == 1 ) { 102 return b+c; 103 } 104 if (!p) { 105 p=d*0.3; 106 } 107 if (!a || a < Math.abs(c)) { 108 a = c; 109 var s = p/4; 110 } else { 111 var s = p/(2*Math.PI) * Math.asin (c/a); 112 } 113 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 114 }, 115 elasticOut: function(t, b, c, d, a, p){ //正弦增强曲线(弹动渐出) 116 if (t === 0) { 117 return b; 118 } 119 if ( (t /= d) == 1 ) { 120 return b+c; 121 } 122 if (!p) { 123 p=d*0.3; 124 } 125 if (!a || a < Math.abs(c)) { 126 a = c; 127 var s = p / 4; 128 } else { 129 var s = p/(2*Math.PI) * Math.asin (c/a); 130 } 131 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 132 }, 133 elasticBoth: function(t, b, c, d, a, p){ 134 if (t === 0) { 135 return b; 136 } 137 if ( (t /= d/2) == 2 ) { 138 return b+c; 139 } 140 if (!p) { 141 p = d*(0.3*1.5); 142 } 143 if ( !a || a < Math.abs(c) ) { 144 a = c; 145 var s = p/4; 146 } 147 else { 148 var s = p/(2*Math.PI) * Math.asin (c/a); 149 } 150 if (t < 1) { 151 return - 0.5*(a*Math.pow(2,10*(t-=1)) * 152 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 153 } 154 return a*Math.pow(2,-10*(t-=1)) * 155 Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; 156 }, 157 backIn: function(t, b, c, d, s){ //回退加速(回退渐入) 158 if (typeof s == 'undefined') { 159 s = 1.70158; 160 } 161 return c*(t/=d)*t*((s+1)*t - s) + b; 162 }, 163 backOut: function(t, b, c, d, s){ 164 if (typeof s == 'undefined') { 165 s = 3.70158; //回缩的距离 166 } 167 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 168 }, 169 backBoth: function(t, b, c, d, s){ 170 if (typeof s == 'undefined') { 171 s = 1.70158; 172 } 173 if ((t /= d/2 ) < 1) { 174 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 175 } 176 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 177 }, 178 bounceIn: function(t, b, c, d){ //弹球减振(弹球渐出) 179 return c - Tween['bounceOut'](d-t, 0, c, d) + b; 180 }, 181 bounceOut: function(t, b, c, d){ 182 if ((t/=d) < (1/2.75)) { 183 return c*(7.5625*t*t) + b; 184 } else if (t < (2/2.75)) { 185 return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; 186 } else if (t < (2.5/2.75)) { 187 return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; 188 } 189 return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; 190 }, 191 bounceBoth: function(t, b, c, d){ 192 if (t < d/2) { 193 return Tween['bounceIn'](t*2, 0, c, d) * 0.5 + b; 194 } 195 return Tween['bounceOut'](t*2-d, 0, c, d) * 0.5 + c*0.5 + b; 196 } 197 }
时间版函数是基于Tween的扩展,利用了Tween的运动样式,当然jQuery也是基于Tween的时间版运动,但是并没有扩展Tween中的更多的运动形式,如果需要,我们还可以扩展jQuery的运动形式,编写一个扩展jQuery的运动插件。
3.jQuery运动插件扩展:
1 $.extend(jQuery.easing , { 2 3 easeIn: function(x,t, b, c, d){ //加速曲线 4 return c*(t/=d)*t + b; 5 }, 6 easeOut: function(x,t, b, c, d){ //减速曲线 7 return -c *(t/=d)*(t-2) + b; 8 }, 9 easeBoth: function(x,t, b, c, d){ //加速减速曲线 10 if ((t/=d/2) < 1) { 11 return c/2*t*t + b; 12 } 13 return -c/2 * ((--t)*(t-2) - 1) + b; 14 }, 15 easeInStrong: function(x,t, b, c, d){ //加加速曲线 16 return c*(t/=d)*t*t*t + b; 17 }, 18 easeOutStrong: function(x,t, b, c, d){ //减减速曲线 19 return -c * ((t=t/d-1)*t*t*t - 1) + b; 20 }, 21 easeBothStrong: function(x,t, b, c, d){ //加加速减减速曲线 22 if ((t/=d/2) < 1) { 23 return c/2*t*t*t*t + b; 24 } 25 return -c/2 * ((t-=2)*t*t*t - 2) + b; 26 }, 27 elasticIn: function(x,t, b, c, d, a, p){ //正弦衰减曲线(弹动渐入) 28 if (t === 0) { 29 return b; 30 } 31 if ( (t /= d) == 1 ) { 32 return b+c; 33 } 34 if (!p) { 35 p=d*0.3; 36 } 37 if (!a || a < Math.abs(c)) { 38 a = c; 39 var s = p/4; 40 } else { 41 var s = p/(2*Math.PI) * Math.asin (c/a); 42 } 43 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 44 }, 45 elasticOut: function(x,t, b, c, d, a, p){ //正弦增强曲线(弹动渐出) 46 if (t === 0) { 47 return b; 48 } 49 if ( (t /= d) == 1 ) { 50 return b+c; 51 } 52 if (!p) { 53 p=d*0.3; 54 } 55 if (!a || a < Math.abs(c)) { 56 a = c; 57 var s = p / 4; 58 } else { 59 var s = p/(2*Math.PI) * Math.asin (c/a); 60 } 61 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b; 62 }, 63 elasticBoth: function(x,t, b, c, d, a, p){ 64 if (t === 0) { 65 return b; 66 } 67 if ( (t /= d/2) == 2 ) { 68 return b+c; 69 } 70 if (!p) { 71 p = d*(0.3*1.5); 72 } 73 if ( !a || a < Math.abs(c) ) { 74 a = c; 75 var s = p/4; 76 } 77 else { 78 var s = p/(2*Math.PI) * Math.asin (c/a); 79 } 80 if (t < 1) { 81 return - 0.5*(a*Math.pow(2,10*(t-=1)) * 82 Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; 83 } 84 return a*Math.pow(2,-10*(t-=1)) * 85 Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b; 86 }, 87 backIn: function(x,t, b, c, d, s){ //回退加速(回退渐入) 88 if (typeof s == 'undefined') { 89 s = 1.70158; 90 } 91 return c*(t/=d)*t*((s+1)*t - s) + b; 92 }, 93 backOut: function(x,t, b, c, d, s){ 94 if (typeof s == 'undefined') { 95 s = 3.70158; //回缩的距离 96 } 97 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; 98 }, 99 backBoth: function(x,t, b, c, d, s){ 100 if (typeof s == 'undefined') { 101 s = 1.70158; 102 } 103 if ((t /= d/2 ) < 1) { 104 return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b; 105 } 106 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; 107 }, 108 bounceIn: function(x,t, b, c, d){ //弹球减振(弹球渐出) 109 return c - this['bounceOut'](x,d-t, 0, c, d) + b; 110 }, 111 bounceOut: function(x,t, b, c, d){ 112 if ((t/=d) < (1/2.75)) { 113 return c*(7.5625*t*t) + b; 114 } else if (t < (2/2.75)) { 115 return c*(7.5625*(t-=(1.5/2.75))*t + 0.75) + b; 116 } else if (t < (2.5/2.75)) { 117 return c*(7.5625*(t-=(2.25/2.75))*t + 0.9375) + b; 118 } 119 return c*(7.5625*(t-=(2.625/2.75))*t + 0.984375) + b; 120 }, 121 bounceBoth: function(x,t, b, c, d){ 122 if (t < d/2) { 123 return this['bounceIn'](x,t*2, 0, c, d) * 0.5 + b; 124 } 125 return this['bounceOut'](x,t*2-d, 0, c, d) * 0.5 + c*0.5 + b; 126 } 127 128 });
当页面需要扩展jQuery运动形式时,可以直接把这个代码拷在我们自己写的js文件中。
4.animation动画:
1 @-moz-keyframes btnPage { 2 0% { -moz-transform: translateY(6px); } 3 50% { -moz-transform: translateY(0); } 4 100% { -moz-transform: translateY(6px); } 5 } 6 @-webkit-keyframes btnPage { 7 0% { -webkit-transform: translateY(6px); } 8 50% { -webkit-transform: translateY(0); } 9 100% { -webkit-transform: translateY(6px); } 10 } 11 @keyframes btnPage { 12 0% { transform: translateY(6px); } 13 50% { transform: translateY(0); } 14 100% { transform: translateY(6px); } 15 } 16 /*btn-page*/ 17 .btn-page { 18 position: fixed; 19 _position: absolute; 20 z-index: 100; 21 left: 50%; 22 bottom: 30px; 23 _bottom: auto; 24 margin-left: -12px; 25 width: 25px; 26 height: 17px; 27 overflow: hidden; 28 cursor: pointer; 29 background-position: 0 -18px; 30 _top: expression(eval(document.documentElement.scrollTop+document.documentElement.clientHeight-this.offsetHeight -30)); 31 -moz-animation: btnPage 1.2s ease-in-out infinite; 32 -webkit-animation: btnPage 1.2s ease-in-out infinite; 33 animation: btnPage 1.2s ease-in-out infinite; 34 }
当我们的页面需要添加CSS3动画时,只需要定义好关键帧和运动的名称,然后把这个运动名称引入我们需要的class里面,就可以利用js动态的添加或改变CSS3动画了。