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?
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.