Home > database >  SwiftUI: path not animating on change of binding animation
SwiftUI: path not animating on change of binding animation

Time:06-08

I'm trying to smoothly animate the change of the length of an arc using the .animate() method of a binding, but the animation does not occur - it just changes suddenly. Here's a minimal example - what am I doing wrong?

I'm using WatchOS.


import SwiftUI

struct TestAnimation: View {
    
    @State var value: Float = 0.2
    
    var body: some View {
        VStack {
            Arc(value: $value)
            Button(action: { self.value  = 0.1 }) {
                Text("Increment")
            }
        }
    }
}

struct Arc: View {

    var value: Binding<Float>

    var body: some View {
        ArcShape(value: value.animation(.easeOut(duration:2)))
            .stroke(lineWidth: 3)
    }
}


struct ArcShape : Shape {

    var value: Binding<Float>

    func path(in rect: CGRect) -> Path {
        var p = Path()
        let arcDegrees: Double = max(360.0 * Double(value.wrappedValue), 2.0)
        let endAngle = -90.0   arcDegrees
        p.addArc(center: CGPoint(x: rect.midX, y:rect.midY), radius: rect.height / 2, startAngle: .degrees(-90), endAngle: .degrees(endAngle), clockwise: false)
        return p
    }
}

enter image description here

CodePudding user response:

We need animatable data in shape and actually do not need binding but animation directly on Arc.

Tested with Xcode 13.4 / watchOS 8.5

demo

Here is main part of fixed code:

struct Arc: View {
    var body: some View {
        ArcShape(value: value)  // << here !!
            .stroke(lineWidth: 3)
            .animation(.easeOut(duration:2), value: value)
    }

// ...

struct ArcShape : Shape {

    var animatableData: CGFloat {
        get { value }
        set { value = newValue }
    }

// ...

Complete test module is here

  • Related