如何在循环或逐帧执行代码中实现变量的指数级/非线性增减
逐帧变量非线性平滑增减的实现思路
方案1:比例乘法调整(最简单的平滑实现)
不需要固定减1,每次给变量乘一个0~1之间的固定系数,就能自动实现越变越慢的平滑衰减效果,无需额外维护其他变量:// 注意原代码变量名拼写为animationLenght,建议修正为animationLength if (animationLength > 1) { // 系数越接近1变化越平缓,0.98代表减速很慢,0.9代表衰减更快 animationLength *= 0.95; // 增加最小阈值避免变量无限趋近于1,卡很久才结束 animationLength = Math.max(1, animationLength); }如果要实现加速递减,反过来维护一个递增的步长变量即可:
let step = 1; if (animationLength > 1) { animationLength -= step; // 步长每次乘大于1的系数实现加速效果 step *= 1.03; animationLength = Math.max(1, animationLength); }方案2:缓动函数映射(效果完全可控)
提前记录变量初始值和总动画帧数,用基础的缓动公式计算当前帧的变量值,支持自定义加速、减速、先加速后减速等任意效果:// 初始化阶段记录固定参数 const initAnimLength = 100; // 变量初始值 const totalFrames = 60; // 总动画帧数 let currentFrame = 0; // 逐帧执行逻辑 if (currentFrame < totalFrames) { currentFrame++; // t为当前动画进度,范围0~1 const t = currentFrame / totalFrames; // ease-in平方曲线:加速递减,变化速度越来越快 const easeInT = t * t; // 替换上面的easeInT可切换效果: // ease-out平方根曲线:减速递减,变化速度越来越慢 // const easeOutT = Math.sqrt(t); // ease-in-out三次方曲线:先加速后减速 // const easeInOutT = t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; // 把缓动计算结果映射到变量的数值区间 animationLength = initAnimLength - (initAnimLength - 1) * easeInT; }方案3:步长线性增减(适合无固定总时长的场景)
维护单独的步长变量,每次步长按固定值增减,实现匀加速/匀减速的变化效果:let step = 0.5; const stepDelta = 0.02; // 每帧步长的固定增量 if (animationLength > 1) { animationLength -= step; step += stepDelta; animationLength = Math.max(1, animationLength); }
内容的提问来源于stack exchange,提问作者Giorgio Martini
相关产品推荐
相关产品推荐

