Alex K
Alex K

Reputation: 83

How to animate shape via state variable in SwiftUI?

Trying to animate right side of rectangle in SwiftUI on tap. But it's not working( It has ratio state var and it's of animatable type (CGFloat). Totally out of ideas why. Please advise.

struct ContentView: View {
    @State private var animated = false

    var body: some View {
        Bar(ratio: animated ? 0.0 : 1.0).animation(Animation.easeIn(duration: 1))
        .onTapGesture {
            self.animated.toggle()
        }.foregroundColor(.green)
    }
}

struct Bar: Shape {
    @State var ratio: CGFloat

    var animatableData: CGFloat {
        get { return ratio }
        set { ratio = newValue }
    }

    func path(in rect: CGRect) -> Path {
        var p = Path()

        p.move(to: CGPoint.zero)

        let width = rect.size.width * ratio
        p.addLine(to: CGPoint(x: width, y: 0))

        let height = rect.size.height

        p.addLine(to: CGPoint(x: width, y: height))

        p.addLine(to: CGPoint(x: 0, y: height))

        p.closeSubpath()

        return p
    }
}

Upvotes: 2

Views: 1122

Answers (1)

Asperi
Asperi

Reputation: 258117

It is not needed @State for animatable data, so fix is simple

struct Bar: Shape {
    var ratio: CGFloat

enter image description here

Tested with this demo view (on Xcode 11.2 / iOS 13.2)

struct TestAnimateBar: View {
    @State private var animated = false

    var body: some View {
        VStack {
            Bar(ratio: animated ? 0.0 : 1.0).animation(Animation.easeIn(duration: 1))
                .foregroundColor(.green)
        }
        .background(Color.gray)
        .frame(height: 40)
        .onTapGesture {
            self.animated.toggle()
        }
    }
}

Upvotes: 1

Related Questions