不熟悉SwiftUI,并且不熟悉此新框架的事实。我想知道是否有人熟悉如何Path
在SwiftUI中设置动画。
例如,给定一个视图,可以这样简单地说RingView
:
struct RingView : View {
var body: some View {
GeometryReader { geometry in
Group {
// create outer ring path
Path { path in
path.addArc(center: center,
radius: outerRadius,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: 360),
clockwise: true)
}
.stroke(Color.blue)
// create inner ring
Path { path in
path.addArc(center: center,
radius: outerRadius,
startAngle: Angle(degrees: 0),
endAngle: Angle(degrees: 180),
clockwise: true)
}
.stroke(Color.red)
.animation(.basic(duration: 2, curve: .linear))
}
}
.aspectRatio(1, contentMode: .fit)
}
}
显示的内容是:
现在,我想知道如何对内圈进行动画处理,即蓝线内的红线。我想要做的动画将是一个简单的动画,其中路径从头开始出现并遍历到结束。
使用CoreGraphics和旧的UIKit框架,这相当简单,但是似乎没有.animation(.basic(duration: 2, curve: .linear))
在内部路径中添加简单内容并显示带有withAnimation
块的视图的功能。
我查看了SwiftUI上提供的Apple教程,但实际上它们仅涵盖了更深入的视图(例如)上的移动/缩放动画Image
。
关于如何为Path
或Shape
在SwiftUI中设置动画的任何指导?
WWDC会话237(使用SwiftUI构建自定义视图)中展示了路径的动画。关键是使用AnimatableData。您可以跳到31:23,但我建议您至少在27:47分钟开始。
您还需要下载示例代码,因为方便的是,演示中未显示(也未说明)有趣的部分:https : //developer.apple.com/documentation/swiftui/drawing_and_animation/building_custom_views_in_swiftui
更多文档: 自从我最初发布答案以来,我继续研究如何为Path设置动画,并发布了一篇有关Animatable协议以及如何将其与Paths一起使用的详尽解释:https : //swiftui-lab.com/swiftui- animations-part1 /
更新:
我一直在使用形状路径动画。这是GIF。
这是代码:
重要说明:该代码无法在Xcode Live Previews上进行动画处理。它需要在模拟器或真实设备上运行。
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 }
}
}