我是 SwiftUI 新手,但我对 Storyboard 有很好的了解。
一开始我想从一些动画开始,但其中一个有问题:
我知道
@State
变量、.onAppear
事件、使用 autoreverse
布尔值重复动画,但我不知道如何使用它们来成为最佳分辨率。
我希望有人能帮助我。
@State var element_appeared : Bool = false
Image(systemName: "paperplane.fill")
.resizable()
.frame(width: element_appeared ? 50 : 0, height: element_appeared ? 50 : 0)
.onAppear() {
element_appeared.toggle()
}
.animation(.easeInOut)
这就是开头动画的工作原理。我认为我必须处理
element_appeared
变量,但我真的不知道如何..
您可以创建一个枚举,因为您的动画有两个以上的状态。然后使用
DispatchQueue
延迟第二个动画。
这是一个演示:
enum AnimationState {
case notAppeared, appeared, animating
}
struct ContentView: View {
@State private var animationState: AnimationState = .notAppeared
private let delay: TimeInterval = 1
var body: some View {
Image(systemName: "paperplane.fill")
.resizable()
.frame(width: imageSize, height: imageSize)
.onAppear {
withAnimation(.easeInOut(duration: delay)) {
animationState = .appeared
}
DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
withAnimation(Animation.easeInOut.repeatForever()) {
animationState = .animating
}
}
}
}
private var imageSize: CGFloat {
switch animationState {
case .notAppeared: return 0
case .appeared: return 50
case .animating: return 40
}
}
}
这是一个例子。我使用第二个 @State 来管理不同的动画。
@State var showIcon : Bool = false
@State var animateForever: Bool = false
var body: some View {
Image(systemName: "paperplane.fill")
.resizable()
.frame(width: showIcon ? 50 : 0, height: showIcon ? 50 : 0)
//.opacity(showIcon ? 1.0 : 0.0)
.scaleEffect(animateForever ? 0.8 : 1.0) // 0.8 == 40/50
.onAppear() {
withAnimation(Animation.easeInOut(duration: 1.0)) {
showIcon.toggle()
}
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
withAnimation(Animation.easeInOut(duration: 1.0).repeatForever()) {
animateForever.toggle()
}
}
}
}
根据 @nicksarno 的回答,在第二个动画上用 .
DispatchQueue
替换 delay()
的使用:
struct AnimatingPlaneView: View {
@State private var showIcon = false
@State private var animateForever = false
private var sideSize: Double { showIcon ? 50 : 0 }
var body: some View {
Image(systemName: "paperplane.fill")
.resizable()
.frame(width: sideSize, height: sideSize)
.opacity(showIcon ? 1.0 : 0.0)
.scaleEffect(animateForever ? 0.8 : 1.0)
.onAppear() {
withAnimation(.easeInOut(duration: 1.0)) {
showIcon.toggle()
}
withAnimation(.easeInOut(duration: 1.0).repeatForever().delay(1)) {
animateForever.toggle()
}
}
}
}