如何在SwiftUI中对路径进行动画处理 [英] How to Animate Path in SwiftUI
问题描述
不熟悉SwiftUI,也没有关于这个新框架的文档。我想知道是否有人熟悉如何在SwiftUI中对 Path
进行动画处理。
例如给定一个视图,可以说这个简单的 RingView
:
struct RingView:视图{
var body:some View {
GeometryReader {
组中的几何{
//创建外环路径
路径{path在
path.addArc(center:center,
radius:externalRadius,
startAngle:Angle(degrees:0),
endAngle:Angle(degrees:360),
顺时针:true)
}
.stroke(Color.blue)
//创建内圈
Path {
path中的path path.addArc(中心:中心,
radius:externalRadius,
startAngle:Angle(degrees:0),
endAngle:Angle(degrees:180),
顺时针:true)
}
.stroke( Color.red)
.animation(.basic(持续时间:2,曲线:.linear))
}
}
.aspectRatio(1,contentMode:.fit)
}
}
显示的内容是:
现在,我想知道如何对内环进行动画处理,即红线位于蓝线内。我想做的动画将是一个简单的动画,其中的路径从头开始出现并遍历到结束。
使用CoreGraphics和旧版本,这相当简单UIKit框架,但似乎没有在内部路径中添加简单的 .animation(.basic(duration:2,curve:.linear))
并显示带有 withAnimation
块可以执行任何操作。
我看过SwiftUI上提供的Apple教程,但实际上它们只涵盖了更深入视图(例如 Image)上的移动/缩放动画。
。
有关如何为 Path
或 Shape
在SwiftUI中?
路径的动画显示在WWDC会话237中(
这是代码:
重要提示:该代码在Xcode Live Previews上没有动画。它需要在模拟器或真实设备上运行。
import SwiftUI
struct ContentView:View {
var body:some View {
RingSpinner()。padding(20)
}
}
struct RingSpinner:视图{
@State var pct:Double = 0.0
var animation:Animation {
Animation.basic(持续时间:1.5) .repeatForever(autoreverses:false)
}
变量主体:一些视图{
GeometryReader {
中的几何ZStack {
路径{
中的路径
path.addArc(center:CGPoint(x:geometry.size.width / 2,y:geometry.size.width / 2),
radius:geometry.size.width / 2,
startAngle:角度(度:0),
endAngle:角度(度:360),
Clockwis e: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(在rect中:CGRect)->路径{
let end = pct * 360
var start:如果pct>加倍
(1-lagAmmount){
start = 360 *(2 * pct-1.0)
}否则,如果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),
半径:rect.size.width / 2,
startAngle:角度(度:开始),
endAngle:角度(度:结束),
顺时针:false)
return p
}
var animatableData:Double {
get {return pct}
set {pct = newValue}
}
}
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 possible to animate a Path
in SwiftUI.
For example given a view, lets say this simple 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)
}
}
What is displayed is:
Now I was wondering how we could go about animating the inner ring, that is the red line inside the blue line. The animation I'm looking to do would be a simple animation where the path appears from the start and traverses to the end.
This is rather simple using CoreGraphics and the old UIKit framework but it doesn't seem like adding a simple .animation(.basic(duration: 2, curve: .linear))
to the inner path and displaying the view with a withAnimation
block does anything.
I've looked at the provided Apple tutorials on SwiftUI but they really only cover move/scale animations on more in-depth views such as Image
.
Any guidance on how to animate a Path
or Shape
in SwiftUI?
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 }
}
}
这篇关于如何在SwiftUI中对路径进行动画处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!