移动端 transition动画函数的封装(仿Zepto)以及 requestAnimationFrame动画函数封装(仿jQuery)

时间:2022-09-22 17:39:10

移动端 css3 transition 动画 ,requestAnimationFrame 动画  对于性能的要求,h5优先考虑;

移动端 单页有时候 制作只用到简单的css3动画即可,我们封装一下,没必要引入zepto框架,把zepto的动画模块从Zepto 扒下来,加以改造独立;用于生产环境;下面是 Demo栗子;

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

上面图片对应的 js

         var leftsbox=document.getElementById("leftsbox");
var boxdiv=leftsbox.getElementsByTagName("div");
leftsbox.onclick=function(){
for(var i=0;i<boxdiv.length;i++){
var that=boxdiv[i];
transform(that,{ translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', rotateY:'30deg'},800,'cubic-bezier(0.15, 0.5, 0.25, 1.0)',function(){
this.innerHTML='结束回调'+this.innerHTML;
},100*i);
} //for

  

再看看另外一种 常见的 如下图

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

上面对用的 js 代码

                       var nav=document.querySelector(".nav");
var nava=nav.getElementsByTagName("li");
var content=document.querySelector(".content");
var ulcontent=document.getElementById("ulcontent");
ulcontent.style.width=nav.offsetWidth*nava.length+'px';
for(var i=0;i<nava.length;i++) {
nava[i].index=i;
nava[i].onclick=function(){
var that=this;
var now=-(that.index)*content.offsetWidth+'px'; transform(ulcontent,{translate3d:''+now+',0,0',},'linear',function(){
//console.log('success 回调函数');
})
}//click end
}

  htm结构

 <ul class="nav">
<li ><a >首页</a></li>
<li ><a >插件</a></li>
<li ><a >新闻</a></li>
<li ><a >其他</a></li>
</ul> <div class="content">
<ul id="ulcontent" >
<li ><img src="../../images/1a.jpg"></li>
<li ><img src="../../images/2a.jpg"></li>
<li ><img src="../../images/3a.jpg"></li>
<li style="background:#ddd;" >44444444444</li>
</ul>
</div>

  

基于zepto动画独立出来,原先zepto 动画书写方式

$("#banners").animate(
{
translate3d:'220px,10px,0',
left:'1em',
opacity:0.2,
perspective:'400px',
rotateY:'30deg'
},
800,
'cubic-bezier(0.15, 0.5, 0.25, 1.0)',
function(){ alert('回调'); },
1000
)

  

改写后 独立与zepto的 动画函数 语法如下

transform(dom元素,{ transitionProperty:css值},transitionDuration(单位:毫秒),transitionTiming,transitionend回调,transitionDelay(单位:毫秒)); 

transform(dom元素,animationName,animationDuration(单位:毫秒),animationTiming,animationend回调,animationDelay(单位:毫秒)); 

/*
* js transfrom
* @param obj {obj} 原生dom对象
* @param properties {json} ||string { translate3d:'220px,10px,0',left:'1em',opacity:0.2, rotateY:'30deg'} || animationName 多个可以以逗号分割 如 'fadeIn,sliderDown';
* @param duration {number} css3持续时间 秒 默认400毫秒
* @param ease {str} 默认linear 支持 cubic-bezier(0.42,0,1,1)写法;
* @param callback {function} 回调函数
* @param delay {number} 延迟时间 */
/* http://www.cnblogs.com/surfaces/
* @param properties 为 {} 或者 string ;如果 properties= string 为animation-name
* transform(elem, properties)
* transform(elem, properties, ease)
* transform(elem, properties, ease, delay)
* transform(elem, properties, ease, callback, delay)
* transform(elem, properties, callback)
* transform(elem, properties, callback, delay)
* transform(elem, properties, duration )
* transform(elem, properties, duration, ease)
* transform(elem, properties, duration, delay)
* transform(elem, properties, duration, callback)
* transform(elem, properties, duration, callback,delay)
* transform(elem, properties, duration, ease, delay)
* transform(elem, properties, duration, ease, callback)
* transform(elem, properties, duration, ease, callback,delay) transform(elem,{translateX:'150px',left:'1em',opacity:0.2, rotateY:'40deg'},600,'linear',function(){ console.log('结束回调') },200) ; transform(elem, keyframesName,600,'linear',function(){ console.log('结束回调') },200) ;
*/

  

    

关于兼容性:几乎与zepto一致 ,也支持 动画帧 keyframe,个人觉得  keyframe移动端 兼容性不是很好,尤其手机自带的浏览器(原生app 调用 内嵌H5页面,小问题还是蛮多的),适合无关dom数据操作,只显示美化用;

另外,我们需要了解下  css3 transition-duration的属性写法有多种;如下

1). 过渡单个属性:

 transition-property:opacity;
transition-duration:2s;
transition-timing-function:ease-in;
transition-delay:0;

  

2). 过渡多个属性:
[1]. 上下一一对应型:

transition-property:opacity left;
transition-duration:2s, 4s;
transition-timing-function:ease-in;
transition-delay:0;

  

此时:opacity过渡时间为2s,left过渡时间为4s。

[2]. 循环对应型:

transition-property:opacity left width height;
transition-duration:2s, 4s;
transition-timing-function:ease-in;
transition-delay:0;

  

此时:opacity和width过渡时间为2s,left和height过渡时间为4s。

3). transition简写模式:
顺序为:transition-property transition-duration transition-timing-function transition-delay

/*单个属性:*/
-moz-transition:background 0.5s ease-out 0s;
/*多个属性:*/
-moz-transition:background, 0.5s ease-out 0s, color 0.4 ease-out 0s;

过渡持续时间
transition-duration 属性规定了一个过渡从初始状态到目标状态的持续时间。它接受以秒或毫秒的值(例如,2.3S和2300ms都是指2.3秒)。
尽管规范明确规定了过渡值必须为正数,但 Opera 仍接受-5S的值,至少对于getComputedStyle()来说是这样的。虽然规范中并没有限制属性值的大小,但 Opera 和 IE 不接受低于10ms的值。而 WebKit 在 getComputedStyle()执行中有个小bug,例如:返回值0.009999999776482582s会取代0.01s。

过渡延迟时间
transition-delay 属性规定了在执行一个过渡之前的等待时间,同样使用值。Delay 可以是负值,但这会导致动画无法平滑过渡。
IE 和 Opera 不接受 transition-duration 在-10ms和10ms之间的值。WebKit 的 floating point 也会在这儿出现。

http://www.cnblogs.com/surfaces/

另外属性相似点 animation-name:keyfrmaes1,keyfrmaes2;以逗号分割;

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

其他的移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

zepto核心动画但是实现了大部分常用的动画;在阅读器zepto核心动画源码的 时候,自己手动封装 实践;就机会发现 看似读懂其实不懂;自己正真封装调试后;才发现哪些巧;

封装后的   transform.js  源码如下

参数说明

/*
* js transfrom
* @param obj {obj} 原生dom对象
* @param properties {json} || string { translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', rotateY:'30deg'} ||animation-name
* @param duration {number} css3持续时间 秒 默认400毫秒
* @param ease {str} transition-timing-function 默认linear 支持 cubic-bezier(0.42,0,1,1)写法;
* @param callback {function} 回调函数
* @param delay {number} 延迟时间 */

使用方法

   /* http://www.cnblogs.com/surfaces/
* @param properties 为 {} 或者 string ;如果 properties= string 为animation-name
* transform(elem, properties)
* transform(elem, properties, ease)
* transform(elem, properties, ease, delay)
* transform(elem, properties, ease, callback, delay)
* transform(elem, properties, callback)
* transform(elem, properties, callback, delay)
* transform(elem, properties, duration )
* transform(elem, properties, duration, ease)
* transform(elem, properties, duration, delay)
* transform(elem, properties, duration, callback)
* transform(elem, properties, duration, callback,delay)
* transform(elem, properties, duration, ease, delay)
* transform(elem, properties, duration, ease, callback)
* transform(elem, properties, duration, ease, callback,delay) transform(elem,{translateX:'150px',left:'1em',opacity:0.2,perspective:'400px', rotateY:'40deg'},600,'linear',function(){ console.log('结束回调') },200) ;
transform(elem, keyframesName,600,'linear',function(){ console.log('结束回调') },200) ;
*/

 移动端 transform.js 源码如下;双击直接复制即可; 

;(function(window,document,undefined){var prefix=function(){var div=document.createElement("div");var cssText="-webkit-transition:all .1s;-moz-transition:all .1s; -Khtml-transition:all .1s; -o-transition:all .1s; -ms-transition:all .1s; transition:all .1s;";div.style.cssText=cssText;var style=div.style;var dom="";if(style.webkitTransition){dom="webkit"}else{if(style.MozTransition){dom="moz"}else{if(style.khtmlTransition){dom="Khtml"}else{if(style.oTransition){dom="o"}else{if(style.msTransition){dom="ms"}}}}}div=null;if(dom){return{dom:dom,lowercase:dom,css:"-"+dom+"-",js:dom[0].toUpperCase()+dom.substr(1)}}else{return false}}();var transitionEnd=function(){var el=document.createElement("div");var transEndEventNames={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd",msTransition:"MSTransitionEnd",transition:"transitionend"};for(var name in transEndEventNames){if(el.style[name]!==undefined){return transEndEventNames[name]}}el=null;return false}();var animationEnd=(function(){var eleStyle=document.createElement("div").style;var verdors=["a","webkitA","MozA","OA","msA"];var endEvents=["animationend","webkitAnimationEnd","animationend","oAnimationEnd","MSAnimationEnd"];var animation;for(var i=0,len=verdors.length;i<len;i++){animation=verdors[i]+"nimation";if(animation in eleStyle){return endEvents[i]}}return"animationend"}());var supportedTransforms=/^((translate|rotate|scale)(X|Y|Z|3d)?|matrix(3d)?|perspective|skew(X|Y)?)$/i;var dasherize=function(str){return str.replace(/::/g,"/").replace(/([A-Z]+)([A-Z][a-z])/g,"$1_$2").replace(/([a-z\d])([A-Z])/g,"$1_$2").replace(/_/g,"-").toLowerCase()};function transform(obj,properties,duration,ease,callback,delay){if(!obj){return}if(typeof duration=="undefined"){duration=400;ease="linear";callback=undefined;delay=undefined}if(typeof duration=="string"){if(typeof ease=="number"){delay=ease;callback=undefined}if(typeof ease=="function"){delay=callback;callback=ease}ease=duration;duration=400}else{if(typeof duration=="function"){if(typeof ease=="number"){delay=ease}callback=duration;duration=400;ease="linear"}else{if(typeof duration=="number"){if(typeof ease=="undefined"){ease="linear"}else{if(typeof ease=="string"){ease=ease}else{if(typeof ease=="function"){if(typeof callback=="number"){delay=callback}callback=ease;ease="linear"}else{if(typeof ease=="number"){delay=ease;ease="linear"}}}}if(typeof callback=="number"){delay=callback;callback=undefined}}}}delay=(typeof delay=="number")?delay:0;var endEvent=transitionEnd;var nowTransition=prefix.js+"Transition";var nowTransform=prefix.js+"Transform";var prefixcss=prefix.css;if(!prefix.js){nowTransition="transition";nowTransform="transform";prefixcss=""}var transitionProperty,transitionDuration,transitionTiming,transitionDelay;var animationName,animationDuration,animationTiming,animationDelay;var key,cssValues={},cssProperties,transforms="";var transform;var cssReset={};var css="";var cssProperties=[];transform=prefixcss+"transform";cssReset[transitionProperty=prefixcss+"transition-property"]=cssReset[transitionDuration=prefixcss+"transition-duration"]=cssReset[transitionTiming=prefixcss+"transition-timing-function"]=cssReset[transitionDelay=prefixcss+"transition-delay"]=cssReset[animationName=prefixcss+"animation-name"]=cssReset[animationDuration=prefixcss+"animation-duration"]=cssReset[animationTiming=prefixcss+"animation-timing-function"]=cssReset[animationDelay=prefixcss+"animation-delay"]="";if(typeof properties=="string"){cssValues[animationName]=properties;cssValues[animationDuration]=duration+"ms";cssValues[animationTiming]=(ease||"linear");cssValues[animationDelay]=(delay)+"ms";endEvent=animationEnd}else{endEvent=transitionEnd;for(key in properties){if(supportedTransforms.test(key)){transforms+=key+"("+properties[key]+") "}else{cssValues[key]=properties[key],cssProperties.push(dasherize(key))}}if(transforms){cssValues[transform]=transforms,cssProperties.push(transform)}if(duration>0&&typeof properties==="object"){cssValues[transitionProperty]=cssProperties.join(", ");cssValues[transitionDuration]=duration+"ms";cssValues[transitionTiming]=(ease||"linear");cssValues[transitionDelay]=(delay)+"ms"}}for(var attr in cssValues){css+=dasherize(attr)+":"+cssValues[attr]+";"}obj.style.cssText=obj.style.cssText+";"+css;obj.clientLeft;if(!callback){return}var fired=false;var handler=function(event){if(typeof event!=="undefined"){if(event.target!==event.currentTarget){fired=true;return}}callback&&callback.apply(obj,arguments);fired=true;obj.removeEventListener(endEvent,arguments.callee,false)};if(obj.addEventListener){obj.addEventListener(endEvent,handler,false)}if(!endEvent||duration<=0){setTimeout(function(){handler()});return}setTimeout(function(){if(fired){return}handler()},parseInt((duration+delay)+25))}window.transform=transform})(window,document);

 部分示例 使用代码

 

<style>
*{ margin:0; padding:0;}
ul,li{ list-style:none; margin:0; padding:0;} html{-webkit-touch-callout:none;-webkit-user-select:none;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent; font-size:62.5%; }
body{ font-size:14px;} #leftsbox{ width:88%; height:auto; overflow:hidden; border:2px solid red; margin:0 auto; padding:30px 0;}
#leftsbox div{ width:80px; height:80px; background:#6C6; margin-bottom:10px; position:relative; left:0; backface-visibility:hidden;
-webkit-animation-fill-mode:forwards;
animation-fill-mode:forwards;
} @keyframes keyframesName{
0%{ transform:translateX(0)}
100%{transform:translateX(600px) }
}
@-webkit-keyframes keyframesName{
0%{ -webkit-transform:translateX(0)}
100%{-webkit-transform:translateX(600px) }
} </style>
<div id="leftsbox">
<div class="leftssa" style="background:red">1 lefts 22 RAF</div>
<div class="leftssa " style="width:120px; background:#FF0">2 lefts 22 RAF</div>
<div class="leftssa"> 333lefts 22 RAF</div>
</div> <script> var leftsbox=document.getElementById("leftsbox");
var boxdiv=leftsbox.getElementsByTagName("div");
leftsbox.onclick=function(e){ for(var i=0;i<boxdiv.length;i++){
var that=boxdiv[i];
// transform(that,{ translate3d:'220px,10px,0',left:'1em',opacity:0.2,perspective:'400px', width:'200px', rotateY:'30deg'},800,'cubic-bezier(0.15, 0.5, 0.25, 1.0)',function(){
// this.innerHTML='结束回调'+this.innerHTML;
// },1000*i); /* properties json(css3 属性) 或者 string(css3动画名称)
* transform(elem, properties)
* transform(elem, properties, ease)
* transform(elem, properties, ease, delay)
* transform(elem, properties, ease, callback, delay)
* transform(elem, properties, callback)
* transform(elem, properties, callback, delay)
* transform(elem, properties, duration )
* transform(elem, properties, duration, ease)
* transform(elem, properties, duration, delay)
* transform(elem, properties, duration, callback)
* transform(elem, properties, duration, callback,delay)
* transform(elem, properties, duration, ease, delay)
* transform(elem, properties, duration, ease, callback)
* transform(elem, properties, duration, ease, callback,delay)
*/ //测试 properties为 keyframes
var keyframes='keyframesName';
//transform(that, keyframes)
//transform(that, keyframes,'ease')
//transform(that, keyframes,'ease',1000*i)
//transform(that, keyframes,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) //transform(that, keyframes,function(){ this.innerHTML='结束回调'+this.innerHTML;})
//transform(that, keyframes,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) //transform(that, keyframes,600)
//transform(that, keyframes,600,ease')
//transform(that, keyframes,600,1000*i) ;
//transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
//transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ; //transform(that, keyframes,600,'ease',1000*i)
// transform(that, keyframes,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
// transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1020*i) ;
// transform(that, keyframes,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},-20*i) ; //css3 animation-delay 支持负数 直接进入到时间点 //测试 properties为 Json
var json={translate3d:'600px,10px,0',left:'1em',opacity:0.2,perspective:'400px', width:'200px', rotateY:'30deg'}
//transform(that,json);
// transform(that, json,'ease')
//transform(that, json,'ease',1000*i)
//transform(that, json,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) //transform(that, json,function(){ this.innerHTML='结束回调'+this.innerHTML;})
//transform(that, json,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) //transform(that, json,600)
//transform(that, json,600,'ease')
//transform(that, json,600,1000*i) ;
//transform(that, json,600,function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
// transform(that, json,600,function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ; //transform(that, json,600,'ease',1000*i)
//transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;}) ;
transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},1000*i) ;
//transform(that, json,600,'ease',function(){ this.innerHTML='结束回调'+this.innerHTML;},-100*i) ; ////css3 transition-delay 支持负数 直接进入到时间点 } //for end }
</script>

  

唯一的缺点  scrollTop 缓动不支持; 这里有个简易的  函数 类似jquery  语法几乎一样 基于时间 算法 使用 requestAnimationFrame

先看效果

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

相关布局

<ul id="inner" >
<li><a class="on" >护肤</a></li>
<li><a >彩妆</a></li>
<li><a >洗护</a></li>
<li><a >套装</a></li>
</ul> <ul class="uls" id="uls">
<li id='li1'></li>
<li id='li12'></li>
<li id='li3'></li> </ul> <div class="box22">
<div class="boxs">1111111111111111111111111111111111</div>
<div class="boxs">22222222222222222222222222222</div> <div class="boxs">33333333333333333333333</div>
<div class="boxs" style="height:100px;">4444444444444444444最后一个 </div>
</div> <div id="gpTop">tops</div>

上图相关js

  document.getElementById("gpTop").onclick=function(e){
var that=this;
startMove(that,{"scrollTop":0},function(){
that.innerHTML='到顶了';
}); //width: 206px; height: 101px; opacity: 0.3;
} var inner=document.getElementById("inner");
var inlione=inner.getElementsByTagName("li");
var box=document.querySelectorAll(".boxs"); for(var i=0;i<inlione.length;i++) {
inlione[i].index=i;
inlione[i].onclick=function(e){
var that=this;
// console.log(that.index);
var box2=box[that.index];
var nowTop=getOffest(box2).top;
// console.log(nowTop); animate(window,{"scrollTop":nowTop},function(){
//console.log('success');
});
} }

如果通过原生js  获取  jquey的offset().top  的值呢 如下  这里

var getOffest=function (obj){
var top=0,left=0;
if(obj){
while(obj.offsetParent){
top += obj.offsetTop;
left += obj.offsetLeft;
obj = obj.offsetParent;
}
} return{
top : top,
left : left
}
}

animate.js基于 requestAnimationFrame  兼容ie8+    (单位px  未做rem 兼容处理 ,没有jquery的 stop()处理)

语法如下

animate(dom元素,{"left":1300,"opacity":90},持续时间(毫秒),缓动形式(tween函数),回调函数);

			  animate(element,{"left":1300,"opacity":90},2000,'easeOut',function sa(){
console.log('回调函数');
});

为什么要用   requestAnimationFrame  。

浏览器可以优化并行的动画动作,更合理的重新排列动作序列,并把能够合并的动作放在一个渲染周期内完成,从而呈现出更流畅的动画效果。比如,通过requestAnimationFrame(),JS动画能够和CSS动画/变换或SVG SMIL动画同步发生。另外,如果在一个浏览器标签页里运行一个动画,当这个标签页不可见时,浏览器会暂停它,这会减少CPU,内存的压力,节省电池电量。

相信日后  requestAnimationFrame 在移动端发展的前景是相当不错的,目前安卓上感觉还是有点丢帧。抖动明显;

requestAnimationFrame  一个简单的例子

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

var start = null;
var ele = document.getElementById("j_precent");
var progress = 0; function step() {
progress += 1;
ele.style.width = progress + "%";
ele.innerHTML=progress + "%";
if (progress < 100) {
requestAnimationFrame(step);
}
} document.getElementById("btn_run").addEventListener("click", function() {
ele.style.width = "1px";
progress = 0;
step()
}, false);

  

如下   jQuery1.6.2还用 requestAnimationFrame;

// Start an animation from one number to another
custom: function( from, to, unit ) {
var self = this,
fx = jQuery.fx,
raf; this.startTime = fxNow || createFxNow();
this.start = from;
this.end = to;
this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
this.now = this.start;
this.pos = this.state = 0; function t( gotoEnd ) {
return self.step(gotoEnd);
} t.elem = this.elem; if ( t() && jQuery.timers.push(t) && !timerId ) {
// Use requestAnimationFrame instead of setInterval if available
if ( requestAnimationFrame ) {
timerId = true;
raf = function() {
// When timerId gets set to null at any point, this stops
if ( timerId ) {
requestAnimationFrame( raf );
fx.tick();
}
};
requestAnimationFrame( raf );
} else {
timerId = setInterval( fx.tick, fx.interval );
}
}
},

  http://*.com/questions/7999680/why-doesnt-jquery-use-requestanimationframe

为啥jquery 放弃,上面说的比较完善;

animate源码如下

;(function() {

  var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o']; for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
} if (!window.requestAnimationFrame) {
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
} if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
} }()); var getStyle=function (obj,attr){
return obj.currentStyle ? obj.currentStyle[attr]:getComputedStyle(obj)[attr];
} var Tween = {
linear: function (t, b, c, d){ //匀速
return c*t/d + b;
},
easeIn: function(t, b, c, d){ //加速曲线
return c*(t/=d)*t + b;
},
easeOut: function(t, b, c, d){ //减速曲线
return -c *(t/=d)*(t-2) + b;
},
easeBoth: function(t, b, c, d){ //加速减速曲线
if ((t/=d/2) < 1) {
return c/2*t*t + b;
}
return -c/2 * ((--t)*(t-2) - 1) + b;
},
easeInStrong: function(t, b, c, d){ //加加速曲线
return c*(t/=d)*t*t*t + b;
},
easeOutStrong: function(t, b, c, d){ //减减速曲线
return -c * ((t=t/d-1)*t*t*t - 1) + b;
},
easeBothStrong: function(t, b, c, d){ //加加速减减速曲线
if ((t/=d/2) < 1) {
return c/2*t*t*t*t + b;
}
return -c/2 * ((t-=2)*t*t*t - 2) + b;
},
elasticIn: function(t, b, c, d, a, p){ //正弦衰减曲线(弹动渐入)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d*0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p/4;
} else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
elasticOut: function(t, b, c, d, a, p){ //正弦增强曲线(弹动渐出)
if (t === 0) {
return b;
}
if ( (t /= d) == 1 ) {
return b+c;
}
if (!p) {
p=d*0.3;
}
if (!a || a < Math.abs(c)) {
a = c;
var s = p / 4;
} else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
},
elasticBoth: function(t, b, c, d, a, p){
if (t === 0) {
return b;
}
if ( (t /= d/2) == 2 ) {
return b+c;
}
if (!p) {
p = d*(0.3*1.5);
}
if ( !a || a < Math.abs(c) ) {
a = c;
var s = p/4;
}
else {
var s = p/(2*Math.PI) * Math.asin (c/a);
}
if (t < 1) {
return - 0.5*(a*Math.pow(2,10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
}
return a*Math.pow(2,-10*(t-=1)) *
Math.sin( (t*d-s)*(2*Math.PI)/p )*0.5 + c + b;
}
} function animate(obj,json,times,fx,fn){ if( typeof times == 'undefined' ){
times = 400;
fx = 'linear';
} if( typeof times == 'string' ){
if(typeof fx == 'function'){
fn = fx;
}
fx = times;
times = 400;
}
else if(typeof times == 'function'){
fn = times;
times = 400;
fx = 'linear';
}
else if(typeof times == 'number'){
if(typeof fx == 'function'){
fn = fx;
fx = 'linear';
}
else if(typeof fx == 'undefined'){
fx = 'linear';
}
} var iCur = {};
var startTime = +new Date(); for(var attr in json){
iCur[attr] = 0; if( attr == 'opacity' ){
if(Math.round(getStyle(obj,attr)*100) == 0){
iCur[attr] = 0;
}
else{
iCur[attr] = Math.round(getStyle(obj,attr)*100) || 100;
}
}
else if(attr == 'scrollTop' ){
iCur[attr]=window.scrollY||document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;;
}
else{
iCur[attr] = parseInt(getStyle(obj,attr)) || 0;
} } if(obj.timer){
cancelAnimationFrame(obj.timer)
}
//obj.timer=null; function update(){ var changeTime = +new Date();
var scale = 1 - Math.max(0,startTime - changeTime + times)/times; for(var attr in json){ var value = Tween[fx](scale*times, iCur[attr] , json[attr] - iCur[attr] , times ); if(attr == 'opacity'){
obj.style.filter = 'alpha(opacity='+ value +')';
obj.style.opacity = value/100;
}else if(attr == 'scrollTop'){
window.scrollTo(0, value);
}else{
obj.style[attr] = value + 'px';
} } if(scale == 1){
cancelAnimationFrame(obj.timer);
fn&&fn.apply(this, arguments);
}else{
//setup_fps_meters();
obj.timer=requestAnimationFrame(arguments.callee);
} }//update end
// requestAnimationFrame(update); //某些时候 画的过快 有bug
update(); }
Tween.js
/* * t : time 已过时间
* b : begin 起始值
* c : count 总的运动值
* d : duration 持续时间
* */ //Tween.linear();

css cubic-bezier 缓动备份查看  注意点:x1,x2,y1,y2的值范围在[0, 1]。

var easingMap = {
"linear": [0.250, 0.250, 0.750, 0.750],
"ease": [0.250, 0.100, 0.250, 1.000],
"easeIn": [0.420, 0.000, 1.000, 1.000],
"easeOut": [0.000, 0.000, 0.580, 1.000],
"easeInOut": [0.420, 0.000, 0.580, 1.000],
"easeInQuad": [0.550, 0.085, 0.680, 0.530],
"easeInCubic": [0.550, 0.055, 0.675, 0.190],
"easeInQuart": [0.895, 0.030, 0.685, 0.220],
"easeInQuint": [0.755, 0.050, 0.855, 0.060],
"easeInSine": [0.470, 0.000, 0.745, 0.715],
"easeInExpo": [0.950, 0.050, 0.795, 0.035],
"easeInCirc": [0.600, 0.040, 0.980, 0.335],
"easeInBack": [0.600, -0.280, 0.735, 0.045],
"easeOutQuad": [0.250, 0.460, 0.450, 0.940],
"easeOutCubic": [0.215, 0.610, 0.355, 1.000],
"easeOutQuart": [0.165, 0.840, 0.440, 1.000],
"easeOutQuint": [0.230, 1.000, 0.320, 1.000],
"easeOutSine": [0.390, 0.575, 0.565, 1.000],
"easeOutExpo": [0.190, 1.000, 0.220, 1.000],
"easeOutCirc": [0.075, 0.820, 0.165, 1.000],
"easeOutBack": [0.175, 0.885, 0.320, 1.275],
"easeInOutQuad": [0.455, 0.030, 0.515, 0.955],
"easeInOutCubic": [0.645, 0.045, 0.355, 1.000],
"easeInOutQuart": [0.770, 0.000, 0.175, 1.000],
"easeInOutQuint": [0.860, 0.000, 0.070, 1.000],
"easeInOutSine": [0.445, 0.050, 0.550, 0.950],
"easeInOutExpo": [1.000, 0.000, 0.000, 1.000],
"easeInOutCirc": [0.785, 0.135, 0.150, 0.860],
"easeInOutBack": [0.680, -0.550, 0.265, 1.550],
"custom": [0.000, 0.350, 0.500, 1.300],
"random": [Math.random().toFixed(3),
Math.random().toFixed(3),
Math.random().toFixed(3),
Math.random().toFixed(3)]
}

This curve contains values out of range. But fear not young padawan! Just use cubic-bezier(.25,.1,.39,1) as well for Webkit until the bug #45761 fix propagates to Safari.

接近ios 原生 的切换 cubic-bezier(0.42, 0, 0.58, 1.0)

http://www.cnblogs.com/surfaces/

移动端 transition动画函数的封装(仿Zepto)以及  requestAnimationFrame动画函数封装(仿jQuery)

 // transform兼容
    function preTransform() {
        var cssPrefix,
        vendors = {
          '': '',
          Webkit: 'webkit',
          Moz: '',
          O: 'o',
          ms: 'ms'
        },
        testEle = document.createElement('p'),
        cssSupport = {};
 
         // 嗅探特性
        Object.keys(vendors).some(function(vendor) {
            if (testEle.style[vendor + (vendor ? 'T' : 't') + 'ransform'] !== undefined) {
              cssPrefix = vendor ? '-' + vendor.toLowerCase() + '-' : '';
              return true;
            }
        });
 
      function normalizeCss(name) {
        name = name.toLowerCase();
        return cssPrefix ? cssPrefix + name : name;
      }
 
      cssSupport = {
        transform: normalizeCss('Transform'),
      }
 
      return cssSupport.transform;
    }
}());

  

参考资料:

snabbt.js

http://daniel-lundin.github.io/snabbt.js/index.html

jquery.transit.js

Zepto.js

Bootstrap.transition.js jquery.js

														
		

移动端 transition动画函数的封装(仿Zepto)以及 requestAnimationFrame动画函数封装(仿jQuery)的更多相关文章

  1. javascript仿天猫加入购物车动画效果

    javascript仿天猫加入购物车动画效果   注意:首先需要声明的是:代码原思路不是我写的,是在网上找的这种效果,自己使用代码封装了下而已:代码中都有注释,我们最主要的是理解抛物线的思路及在工作中 ...

  2. Android应用系列:仿MIUI的Toast动画效果实现(有图有源码)

    前言 相信有些人用过MIUI,会发现小米的Toast跟Android传统的Toast特么是不一样的,他会从底部向上飞入,然后渐变消失.看起来效果是挺不错的,但是对于Android原生Toast是不支持 ...

  3. 前端笔记之jQuery(上)加载函数的区别&amp&semi;对象&amp&semi;操作HTML&sol;CSS&amp&semi;动画&amp&semi;选择器

    一.jQuery简介 1.0 JavaScript编程比较恶心的地方 恶心1:选择元素麻烦,全线兼容的方法只有getElementById()和getElementsByTagName()两个.其他的 ...

  4. Android应用系列:仿MIUI的Toast动画效果实现

    前言 相信有些人用过MIUI,会发现小米的Toast跟Android传统的Toast特么是不一样的,他会从底部向上飞入,然后渐变消失.看起来效果是挺不错的,但是对于Android原生Toast是不支持 ...

  5. ToastMiui【仿MIUI的带有动画的Toast】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 仿MIUI的带有动画的Toast 效果图 代码分析 ToastMiui类基于WindowManager 为了和Toast用法保持一致 ...

  6. 从普通函数到对象方法 ------Windows窗口过程的面向对象封装

    原文地址:http://blog.csdn.net/linzhengqun/article/details/1451088 从普通函数到对象方法 ------Windows窗口过程的面向对象封装 开始 ...

  7. 高性能封装检测浏览器支持css3属性函数

    css3出来已经很久了,现在来谈判断浏览器是否支持某个css3的属性虽说有点过时了,但是还是可以谈谈的,然后,此篇主要谈的不是判断是否支持,而是怎么封装更好,为什么这么封装,欢迎吐槽. 入题,判断浏览 ...

  8. JS---封装缓动(变速)动画函数---增加任意多个属性&amp&semi;增加回调函数

    封装缓动(变速)动画函数---增加任意多个属性&增加回调函数 回掉函数fn,在所有元素到达目的位置后,判断是否传入一个函数,有就调用 if(fn){fn()}; 这样一次点击,产生多个动画 & ...

  9. 纯 HTML&sol;CSS 高仿 Win10 加载动画

    自己做的超高仿Win10加载动画(应该是全网最像的 HTML 实现了),自己想用就拿去用吧 转圈加载 在线演示 HTML: <div class="loading"> ...

随机推荐

  1. js学习内容的整理

    1.jquery动态添加Table中的一行 function addTableRow(tableId){var html = '<tr>\ ......\ </tr>&quot ...

  2. 挣值管理(PV、EV、AC、SV、CV、SPI、CPI)记忆之我见

    挣值管理(PV.EV.AC.SV.CV.SPI.CPI)记忆之我见 挣值管理法中的PV.EV.AC.SV.CV.SPI.CPI这些英文简写相信把大家都搞得晕头转向的.在挣值管理法中,需要记忆理解的有三 ...

  3. Javascript设计模式之我见:迭代器模式

    大家好!本文介绍迭代器模式及其在Javascript中的应用. 模式介绍 定义 提供一种方法顺序一个聚合对象中各个元素,而又不暴露该对象内部表示. 类图及说明 Iterator抽象迭代器 抽象迭代器负 ...

  4. Java集合之ArrayList源码分析

    1.简介 List在数据结构中表现为是线性表的方式,其元素以线性方式存储,集合中允许存放重复的对象,List接口主要的实现类有ArrayList和LinkedList.Java中分别提供了这两种结构的 ...

  5. spring boot oauth2的一些记录

    oauth2及时从一个项目A申请另一个项目B的访问的时候,不用在项目A输入项目B的用户名和密码,个人理解先跳转到项目B,利用项目B的用户名和密码得到一个code之类的,这里有点像openID,不过不是 ...

  6. python,魔法方法指南

    1.简介 本指南归纳于我的几个月的博客,主题是 魔法方法 . 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加“魔法”的特殊方法. 它们经常是两个下划线包围来命名的 ...

  7. rabbitmq 配置集群镜像

  8. Android之电话拨号和短信

    拨打电话号码,需要添加权限设置,在安装的应用程序信息中可以看到此权限信息Intent doSth=new Intent();//意图:你想做什么呢?doSth.setAction(Intent.ACT ...

  9. Android无法访问本地服务器(localhost&sol;127&period;0&period;0&period;1)的解决方案

    [Android无法访问本地服务器(localhost/127.0.0.1)的解决方案] 在Android开发中通过localhost或127.0.0.1访问本地服务器时,会报Java.NET.Con ...

  10. 记一次生产环境axis2服务特别慢的问题。

    情况如下: 某服务,在测试环境测试的时候整个响应过程也就0.5s左右,测试环境和生产环境axis2版本一致,tomcat版本一致,但是生产环境需要差不多20S. 后来,越来越慢,导致服务一起来,整个生 ...