缓动的计算方式

缓动属于非均速线性运动,它可以使元素的运动显得更加真实、自然、流畅。

它是基于初始值,结束值,作用域公式来实现的。


📐 数学公式

【思考与演算原理-step1】

increase = ( 10 - 0 ) * ease = 1.5;
increase = ( 10 - 1.5 ) * ease = 1.275;
increase = ( 10 - 1.5 - 1.275 ) * ease = 1.08375;
...
increase = ( 10 - 1.5 - 1.275 - ... ) * ease = 0.075;

结果趋近于0 


【思考与演算原理-step2】

increase1 = ( 10 - 0 ) * ease = 1.5;
increase2 = ( 10 - 1.5 ) * ease = 1.275;
increase3 = ( 10 - 1.5 - 1.275 ) * ease = 1.08375;
...
increase999 = ( 10 - 1.5 - 1.275 - ... ) * ease = 0.075;


result = 10 - increase1 = 8.5000000;
result = 10 - increase1 - increase2 = 7.2250000;
result = 10 - increase1 - increase2 - increase3 = 6.1412500;
result = 10 - increase1 - increase2 - increase3 - ... - increase999 ≈ 0.0000000


//结果,无限趋近于 0

8.5000000
7.2250000
6.1412500
5.2200625
4.4370531
3.7714952
...
0.0000001
0.0000000

📌 JavaScript

参考代码:index.js

/*
* 一个缓动无限趋近于 0 (目标值)的算法
*
* @returns NULL
*/

let increase = 0;
let anime = null;
const ease = 0.15;

export function render() {
    anime = requestAnimationFrame(render);
    increase += (10 - increase) * ease;

    /* 科学计数法需要转数字 */
    const res = parseFloat(10 - increase).toFixed(7);
    console.log('res: ', res);

    /* 停止动画 */
    if (increase === 9.999999999999995) window.cancelAnimationFrame(anime);
}



/*
 * 常见的缓动函数写法
 *
  * @param {Number} t - 时间(动画开始后经过的时间量。通常从 0 开始,并使用循环或其他更新功能缓慢增加。)
  * @param {Number} b - 起始值(动画的起始点。通常它是一个静态值,例如可以从 0 开始。)
  * @param {Number} c - 值的变化(从起点到终点所需的变化量。它通常也是一个静态值。)
  * @param {Number} d - 持续时间(动画将消耗的时间量。通常也是一个静态值。)
  * @returns {Number}
 */
export function easeLinear(t, b, c, d) {
    return c * t / d + b;
}

export function easeInQuad(t, b, c, d) {
    return c * (t /= d) * t + b;
}

export function easeOutQuad(t, b, c, d) {
    return -c * (t /= d) * (t - 2) + b;
}

export function easeInOutQuad(t, b, c, d) {
    if ((t /= d / 2) < 1) return c / 2 * t * t + b;
    return -c / 2 * ((--t) * (t - 2) - 1) + b;
}

测试:test.js

import { render, easeInQuad } from './index';

/*
调试面板的数字将从10到0缓动递减,输出效果: 8.5000000 -> 7.2250000 -> 6.1412500 -> ... ->  0.0468624 -> ... -> 0.0000000
*/
render();


/*
参数:duration: 1500毫秒, start: 开始时间, from: 开始的数值(可以当做像素使用),  to: 结束的数值
*/
const duration = 1500;

function anime() {

    const start = new Date().getTime();
    const from = 0;
    const to = 100;
    let requestId;

    const loop = function () {

        const time = new Date().getTime() - start;
        const val = easeInQuad(time, from, to - from, duration);

        const percent = val / 100;
        console.log(percent);

        if (time < duration) {
            requestId = window.requestAnimationFrame(loop);
        } else {
            window.cancelAnimationFrame(requestId);
        }
    };
    requestId = window.requestAnimationFrame(loop);

}

/*
调试面板的数字将从0到1缓动递减,输出效果: 0.00045511111111111105 -> 0.0005444444444444445 -> ... ->  0.05601111111111111 -> ... -> 0.984064 -> 1.0053404444444443
*/
anime();