Creating a Repeating Animation in SwiftUI

New.gif

SwiftUI is so amazing because of how much it takes care of for you. When you update the state your view updates automatically. Throw a call to withAnimation in there and it will even animate the changes! But what if you want an animation that repeats?

Creating the Animation

First thing we need to do is set up our View with something we want to animate. For this example we’ll animate the scale of some text to make it grow and shrink repeatedly.

struct ContentView: View {
    @State var isAtMaxScale = false

    private let maxScale: CGFloat = 2

    var body: some View {
        Text("Animations")
            .font(.largeTitle)
    }
}

The additional properties, isAtMaxScale and maxScale, are how the animation is going to be controlled. By checking isAtMaxScale we can set different values for the scale of the Text, switching it between 1 and maxScale. You can set the scale of a View with the scaleEffect modifier:

Text("Animations")
    .font(.largeTitle)
    .scaleEffect(isAtMaxScale ? 1 : 0)

Now when we toggle isAtMaxScale the scale of the Text adjusts automatically. But, now we need some way to toggle isAtMaxScale to kick off the animation. You could use a button to trigger it, but if you want the animation to start right away you can use the onAppear modifier, and give it an animation with withAnimation.

Text("Animations")
    .font(.largeTitle)
    .scaleEffect(isAtMaxScale ? 1 : 0)
    .onAppear {
        withAnimation(.easeInOut) {
            self.isAtMaxScale.toggle()
        }

When you call withAnimation you give it an Animation to use, then tell it what it is you want to animate. In our case the Animation curve being used is .easeInOut, and the state property being animated is isAtMaxScale.

Making an Animation Repeat

So the code above gives us our animation, but the problem is it still doesn’t repeat. Luckily it’s super easy to create your own animation that repeats!

private let animation = Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)

Here’s an animation that uses the same easeInOut curve as we were using before, but this time it has a duration of 1 second. It also has a modifier on it to repeatForever, which is all you need to make a repeating animation! And since we want it to look smooth scaling from small-to-big and back again autoreverses is true.

Here’s the full code:

struct ContentView: View {
    @State var isAtMaxScale = false

    private let animation = Animation.easeInOut(duration: 1).repeatForever(autoreverses: true)
    private let maxScale: CGFloat = 2

    var body: some View {
        Text("Animations")
            .font(.largeTitle)
            .scaleEffect(isAtMaxScale ? maxScale : 1)
            .onAppear {
                withAnimation(self.animation, {
                    self.isAtMaxScale.toggle()
                })
            }
    }
}
Previous
Previous

Updating Your View for Dark Mode in SwiftUI

Next
Next

How to Layer Views in SwiftUI Using ZStack