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;};
相關文章
相關標籤/搜索