Being unfamiliar with SwiftUI and the fact that there is not much documentation on this new framework yet. I was wondering if anyone was familiar with how it would be possib
Animation of paths is showcased in the WWDC session 237 (Building Custom Views with SwiftUI). The key is using AnimatableData. You can jump ahead to 31:23, but I recommend you start at least at minute 27:47.
You will also need to download the sample code, because conveniently, the interesting bits are not shown (nor explained) in the presentation: https://developer.apple.com/documentation/swiftui/drawing_and_animation/building_custom_views_in_swiftui
More documentation: Since I originally posted the answer, I continued to investigate how to animate Paths and posted an article with an extensive explanation of the Animatable protocol and how to use it with Paths: https://swiftui-lab.com/swiftui-animations-part1/
Update:
I have been working with shape path animations. Here's a GIF.
And here's the code:
IMPORTANT: The code does not animate on Xcode Live Previews. It needs to run either on the simulator or on a real device.
import SwiftUI
struct ContentView : View {
var body: some View {
RingSpinner().padding(20)
}
}
struct RingSpinner : View {
@State var pct: Double = 0.0
var animation: Animation {
Animation.basic(duration: 1.5).repeatForever(autoreverses: false)
}
var body: some View {
GeometryReader { geometry in
ZStack {
Path { path in
path.addArc(center: CGPoint(x: geometry.size.width/2, y: geometry.size.width/2),
radius: geometry.size.width/2,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: 360),
clockwise: true)
}
.stroke(Color.green, lineWidth: 40)
InnerRing(pct: self.pct).stroke(Color.yellow, lineWidth: 20)
}
}
.aspectRatio(1, contentMode: .fit)
.padding(20)
.onAppear() {
withAnimation(self.animation) {
self.pct = 1.0
}
}
}
}
struct InnerRing : Shape {
var lagAmmount = 0.35
var pct: Double
func path(in rect: CGRect) -> Path {
let end = pct * 360
var start: Double
if pct > (1 - lagAmmount) {
start = 360 * (2 * pct - 1.0)
} else if pct > lagAmmount {
start = 360 * (pct - lagAmmount)
} else {
start = 0
}
var p = Path()
p.addArc(center: CGPoint(x: rect.size.width/2, y: rect.size.width/2),
radius: rect.size.width/2,
startAngle: Angle(degrees: start),
endAngle: Angle(degrees: end),
clockwise: false)
return p
}
var animatableData: Double {
get { return pct }
set { pct = newValue }
}
}