Search code examples
iosswiftswiftuiuikit

Easing functions for using CADisplayLink


I need to manually animate something frame by frame in SwiftUI using CADisplayLink, which provides me frame to frame updates. For animating a value from a to b in a linear fashion, the implementation is trivial, simply calculate a rate of change with (b-a) / duration and apply this delta to the value on every frame.

However, I'm not finding any information on how to do frame to frame updates when the animation isn't linear. I can, of course, create the easing functions myself using say, for example, the numeric package, but it seems too common of a use case for needing so much manual implementation.

Where are the out-of-the-box easing functions from Apple? There should be a package of easing functions that allows me to retrieve y using x, yet this post suggests that there aren't any?


Solution

  • If you can use SwiftUI and have a minimum deployment version of iOS 17, you can use UnitCurve.

    A function defined by a two-dimensional curve that maps an input progress in the range [0,1] to an output progress that is also in the range [0,1]. By changing the shape of the curve, the effective speed of an animation or other interpolation can be changed.

    You can pass in a progress, which is the percentage of the animation that's elapsed, then get a new progress value to use when calculating the current state of the value being animated.

    let newProgress = UnitCurve.easeInOut.value(at: progress)
    let newValue = a + (b - a) * newProgress
    

    If you need some other animation curves, https://easings.net/ is a good reference for commonly used curves. It also includes the math to produce the curve at the bottom of each page.