Я пытаюсь анимировать дугу слева и справа от ее центра (270 градусов в терминах формы). Для этого требуются анимационные данные, которые я добавил, но дуга по-прежнему не анимируется.

Вид с использованием дуги ниже. Я прокомментировал свои намерения свойствами.

struct AverageGauge: View {
    
    @State var endAngle: Angle = Angle(degrees: 271.0)
    
    var clockwise: Bool {
        get { endAngle.degrees > 270 ? false : true }
    }
    

    
    var body: some View {
        Arc(startAngle: .degrees(270), endAngle: endAngle,
            clockwise: clockwise)
            .stroke(.red, style: StrokeStyle(lineWidth: 10, lineCap: .round, lineJoin: .round))
            .frame(width: 300, height: 300)
           // Tap gesture as stand in for changing data
            .onTapGesture {
                withAnimation(Animation.easeIn(duration: 10.0)) {
                    endAngle = Angle(degrees: Double.random(in: 180...360))
                }
            }
    }
}

struct Arc: Shape {
    var startAngle: Angle
    var endAngle: Angle
    var clockwise: Bool
    
    // Animatable endAngle
    var endAngleAnimatable: Angle {
        get { endAngle }
        set { endAngle = newValue }
    }
    
    // Animatable clockwise bool 
    var clockwiseAnimatable: Bool {
        get { clockwise }
        set { clockwise = newValue }
    }
    
    func path(in rect: CGRect) -> Path {
        var path = Path()
        path.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rect.width / 2, startAngle: startAngle, endAngle: endAngleAnimatable, clockwise: clockwiseAnimatable)

        return path
    }
}

Когда я устанавливаю clockwise в Arc на константу, она все равно не анимируется, поэтому я полагаю, что Bool не является причиной проблемы.

Вот гифка дуги, которая мгновенно перерисовывается, а не анимируется: arc

0
Ja5onHoffman 2 Фев 2022 в 19:04
Для этого нужен минимальный воспроизводимый пример (MRE). Какую форму Arc вы используете? Пользовательские фигуры нельзя анимировать просто потому, что они Shapes.
 – 
Yrb
2 Фев 2022 в 19:17
Дуга добавлена ​​вместе с анимацией.
 – 
Ja5onHoffman
2 Фев 2022 в 19:28
1
Отвечает ли это на ваш вопрос stackoverflow.com/a/61221522/12299030?
 – 
Asperi
2 Фев 2022 в 19:57

2 ответа

Я получил эту работу, используя Double для endAngle, а не Angle. Затем Double преобразуется в Angle с использованием .degrees(Double) в дуге. Я предполагаю, что создание Angle не анимируется.

0
Ja5onHoffman 2 Фев 2022 в 20:19
1
Для работы ваши анимируемые данные должны соответствовать VectorMath. По сути, когда вы пишете Shape, вы должны научить его анимировать.
 – 
Yrb
2 Фев 2022 в 20:34
Хорошо… Angle соответствует VectorArithmetic, и он работает без использования Double. Добавлен ответ.
 – 
Ja5onHoffman
2 Фев 2022 в 22:36

Согласно предложению @Yrb, приведенному выше, я согласовал Angle с VectorArithmetic, и анимация работает без необходимости изменять endAngle выполнение Double:

extension Angle: VectorArithmetic {
    
    public static var zero = Angle(degrees: 0.0)
    
    public static func + (lhs: Angle, rhs: Angle) -> Angle {
        Angle(degrees: lhs.degrees + rhs.degrees)
    }
    
    public static func - (lhs: Angle, rhs: Angle) -> Angle {
        Angle(degrees: lhs.degrees - rhs.degrees)
    }
    
    public static func += (lhs: inout Angle, rhs: Angle) {
        lhs = Angle(degrees: lhs.degrees + rhs.degrees)
    }
    
    public static func -= (lhs: inout Angle, rhs: Angle) {
        lhs = Angle(degrees: lhs.degrees - rhs.degrees)
    }
    
    public mutating func scale(by rhs: Double) {
        self.degrees = self.degrees * rhs
    }
    
    public var magnitudeSquared: Double {
        get { 0.0 }
    }
}

magnitudeSquared реализован неправильно. Просто заглушка-наполнитель.

0
Ja5onHoffman 2 Фев 2022 в 22:35