Circular Animation using Animatable in SwiftUI

DevTechie Inc
Jan 29, 2023


Circular Animation using Animatable in SwiftUI

Today we will build circular animation using AnimatableModifier which conforms to the Animatable protocol. We have looked at basics of Animatable in one of the previous article so please check it out here for refresher: link

We will start by building AnimatableModifier called CircularAnimation.

struct CircularAnimation: AnimatableModifier {
    let radius: CGFloat
    var progress: CGFloat = 0var animatableData: CGFloat {
        get {
            progress
        } set {
            progress = newValue
        }
    }func body(content: Content) -> some View {
        content.offset(
            x: radius * cos(progress * (2 * CGFloat.pi)),
            y: radius * sin(progress * (2 * CGFloat.pi))
        )
    }
}
We will add an extension to the View for convenience.

extension View {
    func circularAnimation(radius: CGFloat, progress: CGFloat = 0) -> some View {
        modifier(CircularAnimation(radius: radius, progress: progress))
    }
}
Let’s use this new modifier inside a view.

struct DevTechieShakeAnimation: View {
    @State private var progressA = 0.0
    @State private var progressB = 0.0
    
    var body: some View {
        NavigationStack {
            ZStack {
                Text("DevTechie")
                    .font(.largeTitle.bold())
                Circle()
                    .stroke(Color.indigo, lineWidth: 2)
                    .frame(width: 200)
                Image(systemName: "heart.fill")
                    .font(.title)
                    .foregroundStyle(.orange)
                    .circularAnimation(radius: 100, progress: progressA)
                    .onAppear {
                        withAnimation(Animation.linear(duration: 5).repeatForever(autoreverses: false)) {
                            progressA = 1.0
                        }
                    }
                
                Image(systemName: "heart.fill")
                    .font(.title)
                    .foregroundStyle(.orange)
                    .circularAnimation(radius: 100, progress: progressB)
                    .onAppear {
                        withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) {
                            progressB = 1.0
                        }
                    }
            }
        }
    }
}
With that we have reached the end of this article. Thank you once again for reading. Don’t forget to 👏 and follow 😍. Also subscribe our newsletter at https://www.devtechie.com