2017-12-26 动画

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;};
相关文章
相关标签/搜索