1.初识动画css
>JS动画就是一个定时器,由于定时器的异步因此JS动画也是异步的,不影响其余代码的正常运行,页面上能够有不少的动画,异步
>动画结束后必定要清理定时器函数
2.固定步长的动画优化
>固定步长的动画,固定时间走一步,所以时间是不肯定的动画
>目标值:一屏幕的宽-盒子的宽ui
>this
//设置一个定时器每隔一段时间(频率,定时器的第二个参数),走一步(步长step)
//到达目标值清除定时器
var maxL=$.win("clientWidth")-box.offsetWidth;
//设置步长
var step=5;
var timer=setInterval(()=>{
//先获取当前left值
var l=$.css(box,"left");
//加上步长
l+=step;
//若是最后一步不够步长,若是走了这一步就会超出最大值,因此说最后一步咱们帮他走 ,到达临界值时候直接将最值赋给box便可
if(l>=maxL){
clearInterval(timer);
// $.css(box,"left",maxL);
// //加return就是不让他走最后一步
// return;
l=maxL;
}
//再给box设置加以后的left值
$.css(box,"left",l);
},20)
3.总时间肯定的动画prototype
>动画不只可让left值改变,也可让top,height,width,opacity都有动画效果,对象
>惟有不变的是总时间ci
>总时间duration是设置的 :2000
>left的目标值是target:
$.win("clientWidth")-box.offsetWidth
>opacity的target:1
>left的总路程=target-begin
>left步长step须要计算:每一段时间内(频率,定时器的第二个参数)走的距离
>速度=总路程/总时间,这里是单位时间内走的距离,这里就是每一毫秒走的距离
>step=速度*频率=
(target-begin)/duration * interval
>
let box=document.getElementById("box");
let duration=2000;
let target=$.win("clientWidth")-box.offsetWidth;
let begin=$.css(box,"left");
let interval=20;
let step=interval*(target-begin)/duration;
timer=setInterval(()=>{
begin+=step;
if(begin>=target){
clearInterval(timer);
}
$.css(box,"left",begin);
},interval);
4.匀速直线运动
>让left的值不断变化,time是这里惟一的变量
当前left=起始位置+走过的距离
=begin+速度*时间
=begin+总距离/总时间 *时间
=begin+(target-begin)/duration *time
>
function linear(begin,target,duration,time) {
return begin+(target-begin)/duration *time
}
var duration=2000;
var begin=$.css(box,"left");
var target=$.win("clientWidth")-box.offsetWidth;
var interval=20, time=0;
var timer=setInterval(()=>{
//惟一的变量就是time,每一次加的时间间隔是interval
time+=interval;
//时间到了清除定时器
if(time>=duration){
clearInterval(timer);
time=duration;
}
//利用公式求出当前left,赋给box的left
$.css(box,"left",linear(begin,target,duration,time));
},interval)
5.多维动画
>实现width,height,top,left,opacity五个维度的变化,这五个维度的起始位置,目标值都不同,
>若是变量太多不利于优化,因此将begin与target都写成对象的形式
>
var duration=2000;
var begin={
width:box.offsetWidth,
height:box.offsetHeight,
top:$.css(box,"top"),
left:$.css(box,"left"),
opacity:0
};
var target={
width:300,
height:200,
//注意:这里最大值要减去改变后的宽和高
top:$.win("clientHeight")-200,
left:$.win("clientWidth")-300,
opacity:1
};
var time=0,interval=20,timer=null;
function linear(begin,target,duration,time) {
return begin+(target-begin)/duration*time;
}
timer=setInterval(()=>{
time+=interval;
//临界值判断
if(time>=duration){
clearInterval(timer);
time=duration;
}
//循环target求出每一个维度的linear函数的值
for (var key in target){
$.css(box,key,linear(begin[key],target[key],duration,time))
}
},interval);
6.动画完成以后的操做,增长新的内容
var duration=3000;
var begin={
width:0,
height:0,
left:0,
opacity:0
};
var target={
width:100,
height:100,
left:1000,
opacity:1
};
var time=0,interval=20,timer=null;
function linear(b,t,d,time) {
return b+(t-b)/d*time
};
timer=setInterval(()=>{
time+=interval;
if(time>=duration){
clearInterval(timer);
//既然想要这里完成动画if外面的代码就不能够执行了,此时加上一个return,可是加上return以后就少了一步此时咱们帮他完成最后一步便可,最后一步其实就是让每个维度到达目标值
for(var key in target){
$.css(box,key,target[key])
}
//走完最后一步,在这里动画完成,之后动画完成的操做写在这里便可
box.className="box";
return;
}
for (var key in target){
$.css(box,key,linear(begin[key],target[key],duration,time))
}
},interval)
7.往返运动
var t = 1000;
var b = 0;
var interval = 20;
function linear(b, t, d, time) {
return b + (t - b) / d * time
};
function go() {
var d = 1000;
var time = 0;
timer=setInterval(()=>{
time+=interval;
if(time>=d){
clearInterval(timer);
$.css(box,"left",t);
//当前go完成,执行back
back();
return;
}
$.css(box,"left",linear(b,t,d,time))
},interval);
}
function back() {
var d=3000;
var time=0;
timer=setInterval(()=>{
time+=interval;
if(time>=d){
clearInterval(timer);
$.css(box,"left",b);
//back完成,执行go
go();
return;
}
$.css(box,"left",linear(t,b,d,time))
},interval);
}
go();
8.动画的初步封装
function animation(curEle,target={},duration=2000,interval=13,effect=0,callback) {
//curEle:当前执行动画的元素
//target:目标位置 对象例如{left:1000,top:400,width:300}
//duration:总时间
//interval:频率
//effect:运动曲线
//callback:动画完成以后执行的函数
//处理callback,没传或者是传的不是一个函数了,后面让他执行就报错了,让他等于一个空函数便可
if(typeof callback!="function"){
callback=function () {};
}
//设置其余变量
var time=0,timer=null,begin={};
//根据target给begin赋值
//target必须存在而且是一个对象
if(target&&target.toString()=="[object Object]"){
for(var key in target){
begin[key]=$.css(curEle,key);
}
};
//处理运动曲线
function linear(t, b, c, d) {
return c * t / d + b;
};
function QuadEaseIn(t, b, c, d) {
return c * (t /= d) * t + b;
};
function QuadEaseOut(t, b, c, d) {
return -c * (t /= d) * (t - 2) + b;
};
var effectAry=[linear,QuadEaseIn,QuadEaseOut];
effect=effectAry[effect];
//开启定时器执行动画
timer=setInterval(()=>{
time+=interval;
if(time>=duration){
clearInterval(timer);
for (var key in target){
$.css(curEle,key,target[key]);
}
//让 callback中的this变成当前元素
callback.call(curEle);
return;
};
for(var key in target){
$.css(curEle,key,effect(time,begin[key],target[key]-begin[key],duration));
}
},interval);
};
animation(box,{width:150,height:150,left:1200,top:400},3000,17,1,function () {
this.style.backgroundColor="green";
});
9.封装升级
Element.prototype.animation=function (target,...arg) { //this :当前执行动画的元素 target=target||{}; let begin={}, duration=2000, interval=13, effect=0, time=0, timer=null, numAry=[], fnAry=[], EffectAry=[]; arg.forEach((item)=>{ if(typeof item=="number"){ numAry.push(item); }else if(typeof item=="function"){ fnAry.push(item); } }); for (let i=0;i<numAry.length;i++){ if(numAry[i]>100){ duration=numAry[i]; numAry.splice(i,1); break; } }; interval=numAry[0]?numAry[0]:interval; effect=numAry[1]?numAry[1]:effect; for(let key in target){ begin[key]=$.css(this,key); }; let Effect = { //匀速 Linear: function (t, b, c, d) { return c * t / d + b; }, //指数衰减的反弹缓动 BounceEaseIn: function (t, b, c, d) { return c - Effect.BounceEaseOut(d - t, 0, c, d) + b; }, BounceEaseOut: function (t, b, c, d) { if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b; } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } }, BounceEaseInOut: function (t, b, c, d) { if (t < d / 2) { return Effect.BounceEaseIn(t * 2, 0, c, d) * .5 + b; } return Effect.BounceEaseOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b; }, //二次方的缓动 QuadEaseIn: function (t, b, c, d) { return c * (t /= d) * t + b; }, QuadEaseOut: function (t, b, c, d) { return -c * (t /= d) * (t - 2) + b; }, QuadEaseInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) { return c / 2 * t * t + b; } return -c / 2 * ((--t) * (t - 2) - 1) + b; }, //三次方的缓动 CubicEaseIn: function (t, b, c, d) { return c * (t /= d) * t * t + b; }, CubicEaseOut: function (t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; }, CubicEaseInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) { return c / 2 * t * t * t + b; } return c / 2 * ((t -= 2) * t * t + 2) + b; }, //四次方的缓动 QuartEaseIn: function (t, b, c, d) { return c * (t /= d) * t * t * t + b; }, QuartEaseOut: function (t, b, c, d) { return -c * ((t = t / d - 1) * t * t * t - 1) + b; }, QuartEaseInOut: 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; }, //五次方的缓动 QuintEaseIn: function (t, b, c, d) { return c * (t /= d) * t * t * t * t + b; }, QuintEaseOut: function (t, b, c, d) { return c * ((t = t / d - 1) * t * t * t * t + 1) + b; }, QuintEaseInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) { return c / 2 * t * t * t * t * t + b; } return c / 2 * ((t -= 2) * t * t * t * t + 2) + b; }, //正弦曲线的缓动 SineEaseIn: function (t, b, c, d) { return -c * Math.cos(t / d * (Math.PI / 2)) + c + b; }, SineEaseOut: function (t, b, c, d) { return c * Math.sin(t / d * (Math.PI / 2)) + b; }, SineEaseInOut: function (t, b, c, d) { return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b; }, //指数曲线的缓动 ExpoEaseIn: function (t, b, c, d) { return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b; }, ExpoEaseOut: function (t, b, c, d) { return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b; }, ExpoEaseInOut: function (t, b, c, d) { if (t == 0) return b; if (t == d) return b + c; if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b; return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b; }, //圆形曲线的缓动 CircEaseIn: function (t, b, c, d) { return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b; }, CircEaseOut: function (t, b, c, d) { return c * Math.sqrt(1 - (t = t / d - 1) * t) + b; }, CircEaseInOut: function (t, b, c, d) { if ((t /= d / 2) < 1) { return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b; } return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b; }, //超过范围的三次方缓动 BackEaseIn: function (t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * (t /= d) * t * ((s + 1) * t - s) + b; }, BackEaseOut: function (t, b, c, d, s) { if (s == undefined) s = 1.70158; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b; }, BackEaseInOut: function (t, b, c, d, s) { if (s == undefined) s = 1.70158; if ((t /= d / 2) < 1) { return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b; } return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b; }, //指数衰减的正弦曲线缓动 ElasticEaseIn: function (t, b, c, d, a, p) { if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; var s; !a || a < Math.abs(c) ? (a = c, s = p / 4) : 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; }, ElasticEaseOut: function (t, b, c, d, a, p) { if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; var s; !a || a < Math.abs(c) ? (a = c, s = p / 4) : 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); }, ElasticEaseInOut: function (t, b, c, d, a, p) { if (t == 0) return b; if ((t /= d / 2) == 2) return b + c; if (!p) p = d * (.3 * 1.5); var s; !a || a < Math.abs(c) ? (a = c, s = p / 4) : s = p / (2 * Math.PI) * Math.asin(c / a); if (t < 1) return -.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) * .5 + c + b; } }; for(let key in Effect){ EffectAry.push(Effect[key]) }; effect=EffectAry[effect=effect>=EffectAry.length?0:effect]; timer=setInterval(()=>{ time+=interval; if(time>=duration){ clearInterval(timer); for (let key in target){ $.css(this,key,target[key]); } fnAry.forEach((item)=>{ item.call(this); }); return; } for(let key in target){ $.css(this,key,effect(time,begin[key],target[key]-begin[key],duration)); } },interval); return this;};