1

通过时间扭曲实现缓动动画

经常会见到各类缓动函数,在CSS里面有现成的bounce、elastic等缓动效果直接用。如果在canvas动画中,我们要实现这些缓动函数。直接去思考怎么处理挺头疼的,介绍一种不错的实现方式,源自《HTML5 Canvas核心技术》。

这次的实践在一个封装的基础上,请参考:canvas精灵封装

Begin

缓动动画的本质,是在单位时间内移动不同的距离。

一个简单的公式:距离 = 速度 × 时间;

要实现距离缓动,只有两种方式:

  • 要么保持时间正常流动,实现速度缓动;

  • 要么保持速度不变实现时间扭曲;

下图是elastic效果的距离与时间函数,我乱拿了一个三角函数图像,忽略掉负轴就好

clipboard.png

△V = △S / △T,理论上对距离/时间曲线进行求导,得到速度的变化曲率,改变速度也能实现。

这次实现的是保持速度不变,扭曲时间实现缓动:

1、每个动画时间固定,通过时间能获取到动画进度:

先给出时间扭曲函数:

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;
    };
};

函数图像:

clipboard.png

通过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);
            
        }
    }



lapsec
756 声望25 粉丝

« 上一篇
canvas精灵封装