常常會見到各種緩動函數,在CSS裏面有現成的bounce、elastic等緩動效果直接用。若是在canvas動畫中,咱們要實現這些緩動函數。直接去思考怎麼處理挺頭疼的,介紹一種不錯的實現方式,源自《HTML5 Canvas核心技術》。canvas
此次的實踐在一個封裝的基礎上,請參考:canvas精靈封裝segmentfault
緩動動畫的本質,是在單位時間內移動不一樣的距離。函數
一個簡單的公式:距離 = 速度 × 時間;動畫
要實現距離緩動,只有兩種方式:this
要麼保持時間正常流動,實現速度緩動;spa
要麼保持速度不變實現時間扭曲;code
下圖是elastic效果的距離與時間函數,我亂拿了一個三角函數圖像,忽略掉負軸就好ip
△V = △S / △T,理論上對距離/時間曲線進行求導,獲得速度的變化曲率,改變速度也能實現。ci
此次實現的是保持速度不變,扭曲時間實現緩動:get
先給出時間扭曲函數:
f(x) = ((1 - cos(x * pi * 3)) * (1-x)) + x
轉換成代碼:
var makeElastic = function (passes) {// passes是跳動的次數 passes = passes || 3; return function (percentComplete) { return ((1-Math.cos(percentComplete * Math.PI * passes)) * (1 - percentComplete)) + percentComplete; }; };
函數圖像:
經過Sprite封裝的behavior來實現時間扭曲
var moveBall = { updateBallPosition: function(elapsed){ if (arrow === LEFT){ ball.left -= ball.velocityX * (elapsed/1000); } else{ ball.left += ball.velocityX * (elapsed/1000); } }, execute: function(ball, context,time){ // 核心! // 這裏的animationElapsed是被扭曲過的時間 // getElapsedTime()就是上面的makeElastic // 通過一些封裝,傳入t得出扭曲過的時間 var animationElapsed = pushAnimationTimer.getElapsedTime(), elapsed; elapsed = animationElapsed - this.lastTime; this.updateBallPosition(elapsed); } }