Animation Curves in SwiftUI

DevTechie Inc
Jun 24, 2022


Photo by Osman Rana on Unsplash

Animation curve is the change of animation speed over time. In other words, when you animate a property, the value gets interpolated using an interpolation function.

For example, if you have one second animation with animation curve as easeInOut, the animation will start slow, speed up in the middle and slow down before completion towards the end. EaseInOut is represented in the graph as shown below:

Let’s put this in code:

struct EaseInOutAnimation: View {
    @State private var animate = false
    var body: some View {
        Image(systemName: "airplane")
            .font(.largeTitle)
            .foregroundColor(.orange)
            .offset(x: animate ? 100 : -100)
            .animation(Animation.easeInOut, value: animate)
            .onTapGesture {
                animate.toggle()
            }
    }
}
Having just one animation curve doesn’t give us a clear picture on interpolation change so let’s put a few of them together so we can see the difference.

Other animation curves on graph look like this:

Linear:

EaseIn:

EaseOut:

Default(EaseInOut):

Spring:

Note: animation curves are different but animation starts and ends at the same time.

Code:

struct MultipleAnimationCurves: View {
    @State private var animate = false
    var body: some View {
        VStack {
            Group {
                Text("EaseInOut")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.orange)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeInOut, value: animate)
            }
            
            Group {
                Text("Linear")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.blue)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.linear, value: animate)
            }
            
            Group {
                Text("EaseOut")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.pink)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeOut, value: animate)
            }
            
            Group {
                Text("EaseIn")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.cyan)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeIn, value: animate)
            }
            
            Group {
                Text("Spring")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.mint)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.spring(), value: animate)
            }
        }
        .onTapGesture {
            animate.toggle()
        }
    }
}
You can even specify duration for the animation to play. We will slow down our animation by providing duration param to be five seconds.

Note: Spring animation curve is different from other four animation curves and doesn’t take duration parameter so we will leave it unchanged.

struct MultipleAnimationCurves: View {
    @State private var animate = false
    var body: some View {
        VStack {
            Group {
                Text("EaseInOut")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.orange)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeInOut(duration: 5), value: animate)
            }
            
            Group {
                Text("Linear")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.blue)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.linear(duration: 5), value: animate)
            }
            
            Group {
                Text("EaseOut")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.pink)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeOut(duration: 5), value: animate)
            }
            
            Group {
                Text("EaseIn")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.cyan)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.easeIn(duration: 5), value: animate)
            }
            
            Group {
                Text("Spring")
                    .bold()
                Image(systemName: "airplane")
                    .font(.largeTitle)
                    .foregroundColor(.mint)
                    .offset(x: animate ? 100 : -100)
                    .animation(Animation.spring(), value: animate)
            }
        }
        .onTapGesture {
            animate.toggle()
        }
    }
}
One last thing

SwiftUI animations are interactive, meaning if we trigger animation while another animation is playing SwiftUI accommodates changes from new trigger as well.

To see this in action, I will run the animation again and when our planes are midway, I will tap on VStack again to send them back.

With that we have reached the end of this article. Thank you once again for reading. Subscribe to our weekly newsletter at https://www.devtechie.com