我刚刚在 stackoverflow 中读到,我只能将动画与延迟连接起来,所以我在这里尝试了这个,它只是缩小然后再次缩放圆圈。不幸的是,缩小不起作用!?如果我注释掉不断增长、不断缩小的作品……
struct ContentView: View {
@State var scaleImage : CGFloat = 1
var body: some View {
VStack {
Button(action: {
withAnimation(Animation.easeInOut(duration: 1)) {
self.scaleImage = 0.01
}
withAnimation(Animation.easeInOut(duration: 1).delay(1.0)) {
self.scaleImage = 1
}
}) {
Text ("Start animation")
}
Image(systemName: "circle.fill")
.scaleEffect(scaleImage)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是可能的方法(基于AnimatableModifier
)。实际上,它演示了如何检测当前动画结束并执行某些操作 - 在这种情况下,对于您的缩放场景,只需启动反转即可。
简化并修改了您的示例
struct TestReversingScaleAnimation: View {
@State var scaleImage : CGFloat = 1
var body: some View {
VStack {
Button("Start animation") {
self.scaleImage = 0.01 // initiate animation
}
Image(systemName: "circle.fill")
.modifier(ReversingScale(to: scaleImage) {
self.scaleImage = 1 // reverse set
})
.animation(.default) // now can be implicit
}
}
}
Run Code Online (Sandbox Code Playgroud)
事实上,这里的节目制作人...重要的内嵌评论。
struct ReversingScale: AnimatableModifier {
var value: CGFloat
private let target: CGFloat
private let onEnded: () -> ()
init(to value: CGFloat, onEnded: @escaping () -> () = {}) {
self.target = value
self.value = value
self.onEnded = onEnded // << callback
}
var animatableData: CGFloat {
get { value }
set { value = newValue
// newValue here is interpolating by engine, so changing
// from previous to initially set, so when they got equal
// animation ended
let callback = onEnded
if newValue == target {
DispatchQueue.main.async(execute: callback)
}
}
}
func body(content: Content) -> some View {
content.scaleEffect(value)
}
}
Run Code Online (Sandbox Code Playgroud)
struct ReversingScale: AnimatableModifier {
var value: CGFloat
private var target: CGFloat
private var onEnded: () -> ()
init(to value: CGFloat, onEnded: @escaping () -> () = {}) {
self.target = value
self.value = value
self.onEnded = onEnded // << callback
}
var animatableData: CGFloat {
get { value }
set { value = newValue
// newValue here is interpolating by engine, so changing
// from previous to initially set, so when they got equal
// animation ended
if newValue == target {
onEnded()
}
}
}
func body(content: Content) -> some View {
content.scaleEffect(value)
}
}
Run Code Online (Sandbox Code Playgroud)