常常会见到各种缓动函数,在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); } }