缓动函数与动画

搬运https://www.zybuluo.com/dengzhirong/note/184284

缓动函数, 主要用在控制动画上, 它是一个区间函数
用它来做动画, 实际上就是将这个函数离散化
比如在x轴上取100个点, 计算得到f(x)值 就是得到了这个动画在这100步的变化过程

缓动函数需要四个参数
b 函数开始值
c 函数结束值
d 结束时间(实际上这里并不是真正意义上的时间, 而是离散时的取样)
t 一般为0 也就是从开始值开始变化

例如我将d值设置为100 就是讲这个连续的函数离散为100个点 根据t值(x轴位置)的不同得到不同的结果( f(x)的值 )

两个简单的例子

function timeoutMove() {
    var pos = 0;
    var t1 = +new Date;
    var b = 50, //开始值
        c = 100, //结束值
        d = 100, //运算次数 虽然很多文章这里说时间  但这不是时间 不过这个值决定了执行时间  约1677ms
        t = 0;

    function run() {

        //t =0时 运算结果是 b值
        //t =d时  运算结果是d值
        pos = Math.ceil(Tween.Quad.easeOut(t, b, c - b, d));
        cube.style.top = pos + 'px';
        console.log('t= ',t,'pos=',pos);

        t++;
        timer = setTimeout(run, 1000 / 60);
        if (t >= d) {
            clearTimeout(timer);
            console.log(+new Date - t1);
        }
    }
    run();
}

再来一个RAF的例子

function raqMove() {
    var move = 0,
        t = 0,
        end = 50,
        t1 = +new Date;

    function run() {
        move = Tween.Sine.easeInOut(t, 0, 500, end)
        cube.style.left = move + 'px';
        console.log('t= ',t,'move=',move);

        t++;


        //因为是使用的RAF  不能精确的得到执行结束时间
        //大约执行结束时间是 50*16.7 = 835ms  肯定会比这个时间长
        //16.7 是根据一秒60桢来计算的
        if (t <= end) {
            requestAnimationFrame(run)
        } else {
            console.log(+new Date - t1)
        }
    }
    run();
}

如何将缓动函数真正的用在动画中呢
来看个缓动函数大集合
https://github.com/tweenjs/tween.js/blob/master/src/Tween.js

接下来和动画集合一下

util = {
animate: function(ele, style, time, animate) {
        time = time || 432;
        animate = animate || 'Linear';
        var t1 = +new Date;
        var begins = [], ends= [];
        for (key in style) {
            if(key == 'opacity'){
                begins[key] = parseFloat(window.getComputedStyle(ele)[key])
                console.log(begins[key]);
            }else{
                begins[key] = parseInt(window.getComputedStyle(ele)[key]);
            }
        }
        var d = Math.ceil(time / (1000/60)), //计算次数
            t = 0;

        var b = 1, c = 0.1
        function run() {
            for (key in style) {
                if(key == 'opacity'){
                    ele.style[key] = Tween[animate](t, begins[key], style[key]- b, d);
                }else{
                    ele.style[key] = Tween[animate](t, begins[key], style[key]- begins[key], d) + 'px';
                }
            }
            t++;
            if (t <= d) {
                requestAnimationFrame(run);
            }else{
                console.log(+new Date - t1);
            }
        }
        run();
    }
}    

这样调用就可以

util.animate(cube, {
    top: 500,
    left:100,
    opacity: 0.1
}, 1000, 'easeInOut');