作者热门文章
- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我使用以下函数创建了一个将进度映射到线性函数的实用程序:
public static func map<T: FloatingPoint>(progress: T, min: T, max: T) -> T {
assert(progress >= 0)
assert(progress <= 1)
return min + ((max - min) * progress)
}
这将返回一组线性值,其中,如果最小值为 0,最大值为 100,则每个进度将返回以下值:
0.1 -> 10
0.2 -> 20
0.5 -> 50
0.8 -> 80
0.9 -> 90
我想创建一个类似的函数,将返回值映射到 S 曲线,您离进度的起点和终点越近,结果受结果的影响就越小。例如,这对于使用 CADisplayLink 平滑动画非常有用。上述示例的预期结果如下所示:
0.1 -> 01
0.2 -> 10
0.5 -> 50
0.8 -> 90
0.9 -> 99
我确信有一个相当基本的数学公式,所以任何指针都将不胜感激!
最佳答案
将您的进步视为一个单一参数数学函数。在您当前的情况下,它是一个线性函数,看起来像 y = mx + n
,其中 y
是返回值,n
是 (max - min)
,m
为 1,x
为您的进度值。
要实现您想要的效果,您需要使用 sigmoid function 的置换版本而不是线性的。您需要 x = 0.5 处的中间值,并且只对 0 和 1 之间的值感兴趣。此外,正如维基百科文章所建议的那样,x = -6 和 6 之前和之后的 y 值分别非常接近,所以您只需要将 x 值从 [0, 1]
范围缩放到 [-6, 6]
。下面应该给你一个想法
public static func map<T: FloatingPoint>(progress: T, min: T, max: T) -> T {
assert(progress >= 0)
assert(progress <= 1)
return min + ((max - min) * sigmoid(progress))
}
private static func sigmoid(_ input: FloatingPoint) -> FloatingPoint {
let x = (input - 0.5) * 12.0 // scale the input value to be between -6 and 6
let ex = pow(M_E, x) // M_E is the Euler number and is a Double constant
return ex / (ex + 1) // return the result of the sigmoid function
}
我以前从未使用过FloatingPoint
,所以我不确定这是否可行,可能存在一些类型不匹配。不过我觉得逻辑应该没问题。
关于ios - 如何将值之间的进度映射到 S 曲线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48004402/
我是一名优秀的程序员,十分优秀!