I’m trying to animate an arc to the left and right form its center (270 deg in Shape terms). This requires animatable data, which I’ve added, but the arc still doesn’t seem to animate.
The view using the Arc is below. I’ve commented my intentions with the properties.
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
}
}
When I set the clockwise
in the Arc to a constant, it still doesn’t animate, so I suppose the Bool
isn’t what’s causing the problem.
Here’s a gif of the arc being instantly redrawn rather than animated:
2
Answers
I got this working by using
Double
forendAngle
rather thanAngle
. TheDouble
is then converted to anAngle
using.degrees(Double)
in the arc. I guess creatingAngle
s isn't animatable.Per @Yrb’s suggestion above, I conformed
Angle
toVectorArithmetic
and the animation works without having to changeendAngle
do aDouble
:magnitudeSquared
isn’t properly implemented. Just a filler stub.