AEJoy —— 表达式之弹性(韧性)模拟详解【JS】
效果图
弹性(elastic)
表达式代码与注释
var p = 0.6; ///< 弹性期限 var a = 140; ///< 弹性振幅 /// @note 弹性函数 function outElastic(t, b, c, d, a, p) { if (t == 0) return b; if ((t /= d) == 1) return b + c; if (!p) p = d * .3; if (!a || a < Math.abs(c)) { a = c; var s = p / 4; } else var s = p / (2 * Math.PI) * Math.asin(c / a); return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b); } /// @note 实际调用弹性函数的缓动函数 function easeAndWizz() { var n = 0; /// @note 确保关键帧帧数是大于 0 的 if (numKeys > 0) { n = nearestKey(time).index; ///< 获取最近的关键帧索引 if (key(n).time > time) { ///< 如果最近的关键帧所处时间在当前时间之后(即时间还没到) n--; ///< 则取前一个关键帧的索引 } } try { /// @note 前后两个关键帧 var key1 = key(n); var key2 = key(n + 1); } catch (e) { return null; } /// @note 确定关键帧需要的数据维度 var dim = 1; ///< 该属性至少是一维的 try { key(1)[1]; ///< 数据有第二维度 dim = 2; key(1)[2]; ///< 数据有第三维度 dim = 3; } catch (e) { } t = time - key1.time; ///< 当前时间和前一个关键帧的时间差 d = key2.time - key1.time; ///< 前后俩关键帧的时间差 /// @note 计算关键帧上的属性,用于后期的弹性计算 /// 一维 sX = key1[0]; eX = key2[0] - key1[0]; /// @note 二维 if (dim >= 2) { sY = key1[1]; eY = key2[1] - key1[1]; /// @note 三维 if (dim >= 3) { sZ = key1[2]; eZ = key2[2] - key1[2]; } } if ((time < key1.time) || (time > key2.time)) { return value; } else { /// @note 进行弹性计算 val1 = outElastic(t, sX, eX, d, a, p); /// @note 同样分为三个维度进行计算 switch (dim) { case 1: return val1; break; case 2: val2 = outElastic(t, sY, eY, d, a, p); return [val1, val2]; break; case 3: val2 = outElastic(t, sY, eY, d, a, p); val3 = outElastic(t, sZ, eZ, d, a, p); return [val1, val2, val3]; break; default: return null; } } } (easeAndWizz() || value);
作者:ShaderJoy
链接:https://juejin.cn/post/7016140706842411038