我试图将不同的形状显示为一个接一个的路径动画。动画应该始终从不显示任何内容开始到完成的形状。 我的问题是它只适用于第一个形状,我想是因为
onAppear
。但是,单击“下一个”按钮后,下一个形状不会产生动画。
我尝试使用 pathProgress
值和另一个布尔值,但它要么根本不动画,要么向后动画。
import SwiftUI
struct ContentView: View {
@State var id = 1
@State var pathProgress = 0.0
var body: some View {
VStack {
ConsonantDrawing(id: id)
.trim(from: 0, to: pathProgress)
.stroke(Color.red, style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
.animation(.linear(duration: 4.0), value: pathProgress)
.onAppear {
pathProgress = 1.0
}
.frame(width: UIScreen.main.bounds.width * 0.5, height: UIScreen.main.bounds.height * 0.5)
Spacer()
HStack {
Button {
id -= 1
} label: {
Image(systemName: "arrow.backward.circle")
}
Spacer()
Button {
id += 1
} label: {
Image(systemName: "arrow.forward.circle")
}
}
.padding()
.font(.largeTitle)
}
}
}
struct ConsonantDrawing: Shape {
var id: Int
func path(in rect: CGRect) -> Path {
var path = Path()
let width = rect.size.width
let height = rect.size.height
switch id {
case 1:
path.move(to: CGPoint(x: 0.12069*width, y: 0.97451*height))
path.addLine(to: CGPoint(x: 0.12069*width, y: 0.52102*height))
path.addCurve(to: CGPoint(x: 0.36207*width, y: 0.33497*height), control1: CGPoint(x: 0.12069*width, y: 0.38149*height), control2: CGPoint(x: 0.36207*width, y: 0.33497*height))
path.addCurve(to: CGPoint(x: 0.03448*width, y: 0.27684*height), control1: CGPoint(x: 0.2069*width, y: 0.28846*height), control2: CGPoint(x: 0.03448*width, y: 0.27684*height))
path.addCurve(to: CGPoint(x: 0.98276*width, y: 0.27684*height), control1: CGPoint(x: 0.03448*width, y: -0.02549*height), control2: CGPoint(x: 0.94828*width, y: -0.09526*height))
path.addLine(to: CGPoint(x: 0.98276*width, y: 0.97451*height))
case 2:
path.move(to: CGPoint(x: 0.04412*width, y: 0.24668*height))
path.addCurve(to: CGPoint(x: 0.27941*width, y: 0.19048*height), control1: CGPoint(x: 0.08154*width, y: 0.17525*height), control2: CGPoint(x: 0.20588*width, y: 0.15476*height))
path.addCurve(to: CGPoint(x: 0.35294*width, y: 0.34524*height), control1: CGPoint(x: 0.35294*width, y: 0.22619*height), control2: CGPoint(x: 0.38079*width, y: 0.28888*height))
path.addCurve(to: CGPoint(x: 0.20588*width, y: 0.42857*height), control1: CGPoint(x: 0.32353*width, y: 0.40476*height), control2: CGPoint(x: 0.26471*width, y: 0.42857*height))
path.addCurve(to: CGPoint(x: 0.04412*width, y: 0.32143*height), control1: CGPoint(x: 0.14706*width, y: 0.42857*height), control2: CGPoint(x: 0.05882*width, y: 0.40476*height))
path.addCurve(to: CGPoint(x: 0.07353*width, y: 0.15476*height), control1: CGPoint(x: 0.02941*width, y: 0.2381*height), control2: CGPoint(x: 0.05588*width, y: 0.19048*height))
path.addCurve(to: CGPoint(x: 0.35294*width, y: 0.04762*height), control1: CGPoint(x: 0.10294*width, y: 0.09524*height), control2: CGPoint(x: 0.23438*width, y: 0.04762*height))
path.addCurve(to: CGPoint(x: 0.63235*width, y: 0.19048*height), control1: CGPoint(x: 0.47059*width, y: 0.04762*height), control2: CGPoint(x: 0.60294*width, y: 0.08333*height))
path.addCurve(to: CGPoint(x: 0.57353*width, y: 0.39286*height), control1: CGPoint(x: 0.65523*width, y: 0.27381*height), control2: CGPoint(x: 0.61001*width, y: 0.34856*height))
path.addCurve(to: CGPoint(x: 0.47059*width, y: 0.58333*height), control1: CGPoint(x: 0.51471*width, y: 0.46429*height), control2: CGPoint(x: 0.47059*width, y: 0.53571*height))
path.addCurve(to: CGPoint(x: 0.47059*width, y: 0.83333*height), control1: CGPoint(x: 0.47059*width, y: 0.62143*height), control2: CGPoint(x: 0.47059*width, y: 0.78571*height))
path.addCurve(to: CGPoint(x: 0.98529*width, y: 0.83333*height), control1: CGPoint(x: 0.47059*width, y: 1.02381*height), control2: CGPoint(x: 0.95588*width, y: 1.04762*height))
path.addCurve(to: CGPoint(x: 0.98529*width, y: 0.0119*height), control1: CGPoint(x: 0.98529*width, y: 0.60714*height), control2: CGPoint(x: 0.98529*width, y: 0.19048*height))
case 3:
path.move(to: CGPoint(x: 0.03186*width, y: 0.38372*height))
path.addCurve(to: CGPoint(x: 0.27056*width, y: 0.27907*height), control1: CGPoint(x: 0.04505*width, y: 0.25581*height), control2: CGPoint(x: 0.19913*width, y: 0.25581*height))
path.addCurve(to: CGPoint(x: 0.34199*width, y: 0.44186*height), control1: CGPoint(x: 0.34199*width, y: 0.30233*height), control2: CGPoint(x: 0.36904*width, y: 0.38681*height))
path.addCurve(to: CGPoint(x: 0.17056*width, y: 0.51163*height), control1: CGPoint(x: 0.31341*width, y: 0.5*height), control2: CGPoint(x: 0.24198*width, y: 0.52326*height))
path.addCurve(to: CGPoint(x: 0.03186*width, y: 0.38372*height), control1: CGPoint(x: 0.09913*width, y: 0.5*height), control2: CGPoint(x: 0.04615*width, y: 0.46512*height))
path.closeSubpath()
path.move(to: CGPoint(x: 0.03186*width, y: 0.38372*height))
path.addCurve(to: CGPoint(x: 0.07056*width, y: 0.19767*height), control1: CGPoint(x: 0.01758*width, y: 0.30233*height), control2: CGPoint(x: 0.05341*width, y: 0.23256*height))
path.addCurve(to: CGPoint(x: 0.24198*width, y: 0.05814*height), control1: CGPoint(x: 0.09913*width, y: 0.13953*height), control2: CGPoint(x: 0.17056*width, y: 0.0814*height))
path.addCurve(to: CGPoint(x: 0.37056*width, y: 0.15116*height), control1: CGPoint(x: 0.29913*width, y: 0.09302*height), control2: CGPoint(x: 0.24198*width, y: 0.05814*height))
path.addCurve(to: CGPoint(x: 0.49913*width, y: 0.05814*height), control1: CGPoint(x: 0.49913*width, y: 0.05814*height), control2: CGPoint(x: 0.41341*width, y: 0.11628*height))
path.addCurve(to: CGPoint(x: 0.65627*width, y: 0.19767*height), control1: CGPoint(x: 0.61341*width, y: 0.09302*height), control2: CGPoint(x: 0.64413*width, y: 0.1532*height))
path.addCurve(to: CGPoint(x: 0.54615*width, y: 0.47674*height), control1: CGPoint(x: 0.67849*width, y: 0.27907*height), control2: CGPoint(x: 0.58159*width, y: 0.43348*height))
path.addCurve(to: CGPoint(x: 0.48484*width, y: 0.62791*height), control1: CGPoint(x: 0.5277*width, y: 0.49927*height), control2: CGPoint(x: 0.48484*width, y: 0.5814*height))
path.addCurve(to: CGPoint(x: 0.48484*width, y: 0.81395*height), control1: CGPoint(x: 0.48484*width, y: 0.66512*height), control2: CGPoint(x: 0.48484*width, y: 0.76744*height))
path.addCurve(to: CGPoint(x: 0.98484*width, y: 0.81395*height), control1: CGPoint(x: 0.48484*width, y: 1.02326*height), control2: CGPoint(x: 0.95627*width, y: 1.02326*height))
path.addCurve(to: CGPoint(x: 0.98484*width, y: 0.02326*height), control1: CGPoint(x: 0.98484*width, y: 0.59302*height), control2: CGPoint(x: 0.98484*width, y: 0.19767*height))
default:
path.move(to: CGPoint(x: 0.12069*width, y: 0.97451*height))
path.addLine(to: CGPoint(x: 0.12069*width, y: 0.52102*height))
}
return path
}
}
.animation(.linear(duration: 4.0), value: pathProgress)
都会动画pathProgress
。你似乎不想要那样。据我了解,当 pathProgress
设置为 0 时,您不需要动画 - 它应该仅在 pathProgress
设置为 1 时动画。
所以你应该删除
.animation(.linear(duration: 4.0), value: pathProgress)
。当您想要制作动画时,请使用 withAnimation
,当您不想制作动画时,请不要使用它。
VStack {
ConsonantDrawing(id: id)
.trim(from: 0, to: pathProgress)
.stroke(Color.red, style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
.onAppear {
withAnimation(.linear(duration: 4.0)) {
pathProgress = 1.0
}
}
Spacer()
HStack {
Button {
id -= 1
pathProgress = 0
withAnimation(.linear(duration: 4.0)) {
pathProgress = 1.0
}
} label: {
Image(systemName: "arrow.backward.circle")
}
Spacer()
Button {
id += 1
pathProgress = 0
withAnimation(.linear(duration: 4.0)) {
pathProgress = 1.0
}
} label: {
Image(systemName: "arrow.forward.circle")
}
}
.padding()
.font(.largeTitle)
}
问题是您没有重置
pathProgress
。我所做的是在按下后退或下一个按钮时重置它,并检查当前的 id
是第一个还是最后一个,以避免动画问题。
我还删除了 .animation
视图上的 ConsonantDrawing
修改器,因为它会导致问题,并将动画放在操作中:
struct ContentView: View {
@State var id = 1
@State var pathProgress = 0.0
var body: some View {
VStack {
ConsonantDrawing(id: id)
.trim(from: 0, to: pathProgress)
.stroke(Color.red, style: StrokeStyle(lineWidth: 20, lineCap: .round, lineJoin: .round))
/// Remove this .animation line because is part of the issue!
//.animation(.linear(duration: 4.0), value: pathProgress)
.frame(width: UIScreen.main.bounds.width * 0.5, height: UIScreen.main.bounds.height * 0.5)
Spacer()
HStack {
Button {
guard id != 1 else { return }
id -= 1
pathProgress = 0
withAnimation(.linear(duration: 4)) {
pathProgress = 1.0
}
} label: {
Image(systemName: "arrow.backward.circle")
}
Spacer()
Button {
guard id != 3 else { return }
pathProgress = 0
id += 1
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
withAnimation(.linear(duration: 4)) {
pathProgress = 1.0
}
}
} label: {
Image(systemName: "arrow.forward.circle")
}
}
.padding()
.font(.largeTitle)
}
.onAppear {
print("On appear")
withAnimation(.linear(duration: 4)) {
pathProgress = 1.0
}
}
}
}
结果如下:
让我知道您是如何找到这个解决方案的!