Path AnimatableData在具有SwiftUI的形状对象中不起作用

Path AnimatableData在具有SwiftUI的形状对象中不起作用,path,swiftui,Path,Swiftui,我有一个形状对象(曲线),我正在尝试设置动画: private struct Curve : Shape { private var startAngle : CGFloat private var endAngle : CGFloat private var drawn : Bool private var hAdjustment : CGFloat var clockwise : Bool = true init(side:

我有一个形状对象(曲线),我正在尝试设置动画:

private struct Curve : Shape {
    private var startAngle : CGFloat
    private var endAngle : CGFloat
    private var drawn : Bool
    private var hAdjustment : CGFloat
    
    var clockwise : Bool = true
    
    init(side: CurveSide, isDrawn: Bool) {
        self.startAngle = side.startAngle
        self.endAngle = side.endAngle
        self.hAdjustment = side == .left ? 25 : -25
        self.drawn = isDrawn
    }
    
    var animatableData : CGFloat {
        get { self.endAngle }
        set { self.endAngle = newValue }
    }
    
    func path(in rect: CGRect) -> Path {
        let rotationAdjusment = CGFloat(90.0)
        var baseCirclePath = Path()
        baseCirclePath.addArc(center: CGPoint(x: rect.midX + CGFloat(self.hAdjustment), y: rect.midY),
                              radius: rect.width / 2.3,
                              startAngle: self.drawn ? Angle(degrees: Double(self.startAngle - rotationAdjusment)) : Angle(degrees: 0),
                              endAngle: self.drawn ? Angle(degrees: Double(self.endAngle - rotationAdjusment)) : Angle(degrees: 0),
                              clockwise: !self.clockwise)
        return baseCirclePath
    }
}
这是我尝试使用该形状(曲线)的contentView:

我用这些变量来触发动画:

 @State private var rightCurveDrawn = true
 @State private var leftCurveDrawn = true
这就是我在屏幕上看到的。问题是每次我切换@State变量时,曲线只会出现和消失,没有动画。先谢谢你


看起来您必须自己实现动画值。多有趣啊

要开始,可以在形状中添加以下内容:

private var multiplier = 1.0
var animatableData: CGFloat {
    get { CGFloat(self.multiplier) }
    set { self.multiplier = Double(newValue) }
}
multiplier
没什么特别的,它是我们开发人员增加的价值
animatableData
然而,这就是SwiftUI的魔力。通过将状态更改包装在带有动画的
闭包中,它将立即将形状设置为新值,评估animatableData的最终结果,然后在动画时间内插值这些值

我们可以在animatableData中使用乘数集,如下所示:

    baseCirclePath.addArc(center: CGPoint(x: rect.midX + CGFloat(self.hAdjustment), y: rect.midY),
                          radius: rect.width / 2.3,
                          startAngle: Angle(degrees: Double(self.startAngle - rotationAdjusment) * self.multiplier),
                          endAngle: Angle(degrees: Double(self.endAngle - rotationAdjusment) * self.multiplier),
                          clockwise: !self.clockwise)
不要忘了在init语句的末尾添加以下内容,以便为SwiftUI提供一些可评估的内容:

self.multiplier = self.drawn ? 1 : 0

注 但是请注意,我的
animatableData
的简单实现可能不是您想要的那种动画,但是您可以根据需要自定义它


最后,在这里我学到了我所知道的一切。

你只需要修剪你的形状并指定动画。使用Xcode 12/iOS 14测试(在复制代码上)

struct ContentView:View{
@国家私有变量rightCurveDrawn=false
@状态私有变量leftCurveDrawn=false
var body:一些观点{
HStack{
垫片()
曲线(边:CurveSide.left,isDrawn:self.leftCurveDrawn)
.修剪(从:0到:leftCurveDrawn?1:0)//
self.multiplier = self.drawn ? 1 : 0
struct ContentView: View {
    @State private var rightCurveDrawn = false
    @State private var leftCurveDrawn = false

    var body: some View {
        HStack {
            Spacer()
            Curve(side: CurveSide.left, isDrawn: self.leftCurveDrawn)
                .trim(from: 0, to: leftCurveDrawn ? 1 : 0)       // << here !!
                .stroke(Color.blue, lineWidth: 2)
                .frame(width: 100)
            Curve(side: CurveSide.right, isDrawn: self.rightCurveDrawn)
                .trim(from: 0, to: rightCurveDrawn ? 1 : 0)
                .stroke(Color.red, lineWidth: 2)
                .frame(width:100)
            Spacer()
        }
        .animation(.easeInOut(duration: 2))    // << here !!
        .onAppear {
            self.rightCurveDrawn = true     // can be on button or other
            self.leftCurveDrawn = true      // action
        }
    }
}