缓动的计算方式
缓动属于非均速线性运动,它可以使元素的运动显得更加真实、自然、流畅。
它是基于初始值,结束值,作用域公式来实现的。
📐 数学公式
【思考与演算原理-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();