首页 > 解决方案 > AnimatableData 在 SwiftUI 的 Shape 对象中不起作用

问题描述

我有这个我正在尝试制作动画的 Shape 对象(曲线):

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:

HStack {
       Spacer()
       Curve(side: CurveSide.left, isDrawn: self.leftCurveDrawn)
             .stroke(Color.white, lineWidth: 2)
             .frame(width: 100)
       Curve(side: CurveSide.right, isDrawn: self.rightCurveDrawn)
             .stroke(Color.white, lineWidth: 2)
             .frame(width:100)
       Spacer()
       }

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

 @State private var rightCurveDrawn = true
 @State private var leftCurveDrawn = true

这就是我在屏幕上看到的。问题是每次我切换@State 变量时,曲线只会出现和消失而没有动画。先感谢您。

在此处输入图像描述

标签: pathswiftui

解决方案


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

为了让你开始,你可以在你的形状中添加这样的东西:

private var multiplier = 1.0
var animatableData: CGFloat {
    get { CGFloat(self.multiplier) }
    set { self.multiplier = Double(newValue) }
}

multiplier没什么特别的,这是我们开发人员增加的价值。animatableData然而,这就是 SwiftUI 的魔力。通过将您的状态更改包装在一个withAnimation闭包中,它会立即将您的形状设置为新值,评估 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可能不是您想要的那种动画,但您可以根据需要自定义它。

最后,在这里我学到了关于这个特定问题的所有信息。


推荐阅读