将缓动应用于循环延迟
Applying easing to a loop delay
简单来说,我正在尝试弄清楚如何将缓动应用于循环延迟。
for (i := 0; i < 114; i++) {
// do a task
time.Sleep(//delay before next job)
}
如您所见,这是非常基础的。假设我想在 3 秒内完成整个循环(作业完成时间可以忽略不计,t <= us
)。使用 Penner 方程为每次迭代计算适当的缓和延迟的正确方法是什么?
因此,使用此函数,要模拟从零速度开始的加速度,我应该如何在循环的每次迭代中使用 t
参数来创建适当的睡眠延迟?
func easeInQuad(t float64) {
return math.Pow(t, 2)
}
如果你能帮助我,我将不胜感激。方程式到目前为止还不是问题,但如何在我的用例中使用它们。
我的问题一开始可能看起来像这样:Applying easing to setTimeout delays, within a loop
但是这个没有考虑循环的总时间。
但是,我认为使用重写为仅使用范围 [0,1] 中的一个参数的方程式可能会更好:https://gist.github.com/rezoner/713615dabedb59a15470
根据我的理解,我必须计算抽象 "percentage time elapsed",并以某种方式用缓动函数插入该值。
这个 Node 项目似乎就是这样做的:https://github.com/CharlotteGore/animation-timer,但我还是不知道如何重现它。
我想,你可以使用 time.Ticker。
numLoops := 144
timePerIteration := time.Duration(3) * time.Second / time.Duration(numLoops)
ticker := time.NewTicker(timePerIteration)
for i := 0; i < numLoops; i++ {
// your code
<-ticker.C
}
ticker.Stop()
Penner 方程式基本上需要两个参数:当前进度和可能的总进度。但是,或者,您可以将总进度百分比作为单个参数(作为 0 到 1 之间的值)提供给它,因为无论如何它都是使用当前和总计来计算的。
用你原来的代码,如果你想在3秒内进行114次迭代,最简单的方法是用你的迭代索引作为当前进度,114作为总进度,然后将计算出的延迟因子乘以你的总时长 3.0s.
请注意,Penner 方程式计算从起始位置开始的总位移,而不是每一步的相对位移,因此您实际上需要自己计算该差值。因此this迭代的延迟是本次迭代的总位移(延迟)减去最后一次迭代的总位移:
func DoStuffWithEasing() {
iterations := 114
runTime := 3 * time.Second
for i := 1; i <= iterations; i++ {
// do a task
time.Sleep(easeInQuadDelay(i, iterations, runTime))
}
}
func easeInQuadDelay(c, t int, dur time.Duration) time.Duration {
if c <= 0 || t == 0 { // invalid cases
return 0
}
// This return can be a single-liner, but I split it up for clarity
// Note that time.Durations are fundamentally int64s,
// so we can easily type convert them to float64s and back
this := math.Pow(float64(c)/float64(t), 2)
last := math.Pow(float64(c-1)/float64(t), 2)
return time.Duration((this - last) * float64(dur))
}
简单来说,我正在尝试弄清楚如何将缓动应用于循环延迟。
for (i := 0; i < 114; i++) {
// do a task
time.Sleep(//delay before next job)
}
如您所见,这是非常基础的。假设我想在 3 秒内完成整个循环(作业完成时间可以忽略不计,t <= us
)。使用 Penner 方程为每次迭代计算适当的缓和延迟的正确方法是什么?
因此,使用此函数,要模拟从零速度开始的加速度,我应该如何在循环的每次迭代中使用 t
参数来创建适当的睡眠延迟?
func easeInQuad(t float64) {
return math.Pow(t, 2)
}
如果你能帮助我,我将不胜感激。方程式到目前为止还不是问题,但如何在我的用例中使用它们。
我的问题一开始可能看起来像这样:Applying easing to setTimeout delays, within a loop 但是这个没有考虑循环的总时间。
但是,我认为使用重写为仅使用范围 [0,1] 中的一个参数的方程式可能会更好:https://gist.github.com/rezoner/713615dabedb59a15470
根据我的理解,我必须计算抽象 "percentage time elapsed",并以某种方式用缓动函数插入该值。
这个 Node 项目似乎就是这样做的:https://github.com/CharlotteGore/animation-timer,但我还是不知道如何重现它。
我想,你可以使用 time.Ticker。
numLoops := 144
timePerIteration := time.Duration(3) * time.Second / time.Duration(numLoops)
ticker := time.NewTicker(timePerIteration)
for i := 0; i < numLoops; i++ {
// your code
<-ticker.C
}
ticker.Stop()
Penner 方程式基本上需要两个参数:当前进度和可能的总进度。但是,或者,您可以将总进度百分比作为单个参数(作为 0 到 1 之间的值)提供给它,因为无论如何它都是使用当前和总计来计算的。
用你原来的代码,如果你想在3秒内进行114次迭代,最简单的方法是用你的迭代索引作为当前进度,114作为总进度,然后将计算出的延迟因子乘以你的总时长 3.0s.
请注意,Penner 方程式计算从起始位置开始的总位移,而不是每一步的相对位移,因此您实际上需要自己计算该差值。因此this迭代的延迟是本次迭代的总位移(延迟)减去最后一次迭代的总位移:
func DoStuffWithEasing() {
iterations := 114
runTime := 3 * time.Second
for i := 1; i <= iterations; i++ {
// do a task
time.Sleep(easeInQuadDelay(i, iterations, runTime))
}
}
func easeInQuadDelay(c, t int, dur time.Duration) time.Duration {
if c <= 0 || t == 0 { // invalid cases
return 0
}
// This return can be a single-liner, but I split it up for clarity
// Note that time.Durations are fundamentally int64s,
// so we can easily type convert them to float64s and back
this := math.Pow(float64(c)/float64(t), 2)
last := math.Pow(float64(c-1)/float64(t), 2)
return time.Duration((this - last) * float64(dur))
}