Graphics线性差值函数

Lerp

该函数根据 't' 参数在 [start..end] 范围内进行插值,其中 't' 通常在 [0..1] 范围内。它非常适合回答棘手的数学问题,例如:“56 到 132 之间的 35% 是多少?” 就可以这样计算 lerp(56, 132, 0.35)。

const lerp = (x, y, a) => x * (1 - a) + y * a;

lerp(0, 50, 0.5) // 25
lerp(20, 80, 0)   // 20

t 值通常在 0 到 1 之间,可以认为有点像 0 到 100 之间的百分比范围。上面的例子中,0.5 的 t 值就像 50%。所以函数返回 0 到 50 之间的“50% 位置”:25

Clamp

该函数根据你给它的一个数字,然后规定最小值和最大值。如果你的值在最小值和最大值的范围内,它将返回它。如果它比最小值还小,它将返回最小值,如果比最大值还大则返回最大值。

const clamp = (a, min = 0, max = 1) => Math.min(max, Math.max(min, a));
clamp(24, 20, 30) // 24
clamp(12, 20, 30) // 20
clamp(32, 20, 30) // 30

Clamp对于防止错误的数字进入计算、阻止元素渲染到屏幕外等计算非常方便。

Inverse Lerp

与 lerp 的作用相反。不是传递一个小数和开始结束值,而是传递任何值,它会返回一个小数,无论你传递的值是否落在那个范围内。在内部,它还使用了一个Clamp函数。

const invlerp = (x, y, a) => clamp((a - x) / (y - x));

invlerp(50, 100, 75)  // 0.5
invlerp(50, 100, 25)  // 0
invlerp(50, 100, 125) // 1

对于滚动动画非常有用。比如“用户在本节中滚动了多远?”之类的问题。可以用如下代码巧妙地回答:

const position = el.getBoundingClientRect();
const howFarThrough = invlerp(
  position.top,
  position.bottom,
  window.scrollY
);

Range

它是一种将值从一个数据范围转换为另一个数据范围的函数,非常有用。传入两个数据范围和一个位于数据范围一内的值。

const range = (x1, y1, x2, y2, a) => lerp(x2, y2, invlerp(x1, y1, a));

//    Range 1    Range 2    Value
range(10, 100, 2000, 20000, 50) // 10000

比如,将 window.scrollY 从大范围转换为 0px 到 150px 之间的值。

const position = el.getBoundingClientRect();
const transformY = range(
  position.top,
  position.bottom,
  0,
  150,
  window.scrollY
);

如果用户在该范围上方,它将被限制为 0px。如果在下方,它将被限制为 150 像素。在两者之间的所有位置,它会在值之间均匀插值。

参考

https://gist.github.com/MichaelRocks/f8f66230707bcd88a239
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.ranges/coerce-in.html
https://www.trysmudford.com/blog/linear-interpolation-functions/
https://twitter.com/FreyaHolmer/status/1175925036718444554
https://www.youtube.com/watch?v=NzjF1pdlK7Y

posted @ 2022-05-21 18:09  xiaoluo1234  阅读(127)  评论(0)    收藏  举报