SwiftUI | Animieren Sie diese Pfadform

Oct 20 2020

Ich habe folgenden Fall:

Ich möchte diese Form mit einer benutzerdefinierten Animation umdrehen. Ich weiß nicht, wie ich es richtig beschreiben soll.

Immer wenn ich auf den Pfeil tippe, sollte er sich in den anderen verwandeln . Ohne zu drehen, zu drehen usw. einfach zu transformieren.

Wenn das nicht präzise genug ist, können Sie dies gerne kommentieren!

Demo-Code

struct ContentView: View {
    
    @State private var change = false
    
    private let arrowWidth: CGFloat = 80
    
    
    var body: some View {
        Path { path in
            path.move(to: .zero)
            path.addLine(to: CGPoint(x: arrowWidth/2, y: change ? -20 : 20))
            path.move(to: CGPoint(x: arrowWidth/2, y: change ? -20 : 20))
            path.addLine(to: CGPoint(x: arrowWidth, y: 0))
        }
        .stroke(style: StrokeStyle(lineWidth: 12, lineCap: .round))
        .frame(width: arrowWidth)
        .foregroundColor(.green)
        .animation(.default)
        .onTapGesture { change.toggle() }
        .padding(.top, 300)
    }
}

Wie Sie jetzt sehen können, hat es keine Animation. Ich habe keine Ahnung, wie es geht.

Jede Hilfe wird sehr geschätzt. Vielen Dank!

Hinweis: Ich kann dies nicht mit zwei abgerundeten Rechtecken + einfachem Drehen tun, da ich eine Deckkraftanimation habe, die die Überlappung sichtbar macht.

Antworten

7 Asperi Oct 20 2020 at 20:45

Hier ist ein möglicher Ansatz: Verschieben Sie den Pfad in eine benutzerdefinierte Form und ändern Sie die Parameter als animierbare Eigenschaft. Getestet mit Xcode 12 / iOS 14

struct MyArrow: Shape {
    var width: CGFloat
    var offset: CGFloat
    
    var animatableData: CGFloat {
        get { offset }
        set { offset = newValue }
    }
    
    func path(in rect: CGRect) -> Path {
        Path { path in
            path.move(to: .zero)
            path.addLine(to: CGPoint(x: width/2, y: offset))
            path.move(to: CGPoint(x: width/2, y: offset))
            path.addLine(to: CGPoint(x: width, y: 0))
        }
    }
}

struct ContentView: View {
    
    @State private var change = false
    
    private let arrowWidth: CGFloat = 80
    
    
    var body: some View {
        MyArrow(width: arrowWidth, offset: change ? -20 : 20)
        .stroke(style: StrokeStyle(lineWidth: 12, lineCap: .round))
        .frame(width: arrowWidth)
        .foregroundColor(.green)
        .animation(.default)
        .onTapGesture { change.toggle() }
        .padding(.top, 300)
    }
}