【问题标题】:Applying easing to a loop delay将缓动应用于循环延迟
【发布时间】:2016-08-12 11:17:15
【问题描述】:

简单来说,我想弄清楚如何将缓动应用于循环延迟。

for (i := 0; i < 114; i++) {
    // do a task
    time.Sleep(//delay before next job)
}

如您所见,这是非常基本的。假设我想在 3 秒内完成整个循环(作业完成时间可以忽略不计,t &lt;= 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

据我了解,我必须计算抽象的“已用时间百分比”,并以某种方式使用缓动函数插入该值。

这个 Node 项目似乎就是这样做的:https://github.com/CharlotteGore/animation-timer,但我还是不知道如何重现它。

【问题讨论】:

    标签: loops go delay easing


    【解决方案1】:

    Penner 方程基本上需要两个参数:当前进度和可能的总进度。但是,或者,您可以将总进度百分比作为单个参数(作为 0 到 1 之间的值)提供给它,因为无论如何它都是使用当前和总计来计算的。

    使用您的原始代码,如果您希望在 3 秒内进行 114 次迭代,最简单的方法是将您的迭代索引用作当前进度,并将 114 作为总数,然后将计算出的延迟因子乘以您的总持续时间3.0s。

    请注意,彭纳方程计算的是从起始位置开始的总位移,而不是每一步的相对位移,因此您实际上需要自己计算该差值。因此,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))
    }
    

    https://play.golang.org/p/TTgZUYUvxW

    Graph of the easing

    【讨论】:

    • 哇,非常感谢,你说得这么清楚。所以要使用另一个缓动函数,我必须改变 thislast 的计算方式相同的参数?
    • 没错。顺便说一句,如果你愿意,你甚至可以通过一些函数式编程来动态地完成它。示例:play.golang.org/p/JQCIOWwxEs
    • 好的。最后一件事,我怀疑这是由于您计算延迟的方式,但根据inOutQuad 等式(easings.net/fr#easeInOutQuad)的图表,延迟应该减少-增加-减少而不是增加-停滞在第 57-58 帧-减少。
    • 编辑:我的意思是重现加速/减速的效果,否则它会反映图表。
    • 从技术上讲,delay() 函数正在计算该图的一种穷人导数。它将图表中的 change 从上次迭代返回到当前迭代。它应该从零开始,增加到某个值,然后减小回零。由于quad方程是二次的,导数应该是线性的,但InOut是分段的,这意味着导数也是分段的。 编辑: 链接断开。将此粘贴到 wolframalpha.com: Plot[Piecewise[{{y=2*(x/114)^2,x&lt;=57},{y=(x/114)*(4-2(x/114))-1, x &gt;= 57}}], {x, 0, 114}]
    【解决方案2】:

    我认为,您可以使用 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()
    

    【讨论】:

    • 使用ticker或timer不是问题,而是如何实现penner的缓动方程的返回。
    猜你喜欢
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 2016-08-18
    • 1970-01-01
    • 1970-01-01
    • 2019-05-26
    • 2012-09-19
    • 1970-01-01
    相关资源
    最近更新 更多