在下面的代码中,当您通过更改 @State
属性值点击图像时,该图像会产生动画效果。我希望能够做的是每次 @Published
属性值更改时为图像设置动画,该属性位于 ObservableObject
内部并且动态变化。
使用本地@State属性包装器,工作正常。
struct ContentView: View {
@State private var scaleValue = 1.0
@State private var isAnimating: Bool = true
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: isAnimating)
.onTapGesture {
self.isAnimating.toggle()
self.scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
self.scaleValue = 1.0
}
}
}
}
使用观察到的@Published属性包装器,不起作用。不确定将动画放置在哪里。
struct ContentView: View {
@State private var scaleValue = 1.0
@StateObject private var contentVM = ContentViewModel()
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: contentVM.isAnimating)
// not sure where to add the animation
}
}
编辑:这是工作解决方案:
感谢@Fogmeister 和@burnsi
class ContentViewModel: ObservableObject{
@Published var isAnimatingImage = false
}
struct ContentView2: View {
@StateObject private var contentVM = ContentViewModel()
var body: some View {
@State private var scaleValue = 1.0
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: scaleValue)
.onChange(of: contentVM.isAnimatingImage) {newValue in
animateImage()
}
}
func animateImage(){
scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
scaleValue = 1.0
}
}
}
最佳答案
我认为这里的问题是 .animation
修饰符的错误使用。
您不需要使用不同的 bool 值触发动画。如果动画是通过更改值(在本例中为 scaleValue
)“驱动”的,请在修饰符中使用该值。
看看第一个示例中的动画。它没有完成。它会缩放到所需的大小,然后缩小。但它会在动画中间跳跃,同时向后收缩。
这将是您的第一个示例中的正确实现:
struct ContentView: View {
@State private var scaleValue = 1.0
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: scaleValue)
.onTapGesture {
self.scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
self.scaleValue = 1.0
}
}
}
}
在你的第二个例子中:
class ContentViewModel: ObservableObject{
@Published var scaleValue = 1.0
}
struct ContentView2: View {
@StateObject private var contentVM = ContentViewModel()
var body: some View {
Image(systemName: "circle.fill")
.scaleEffect(contentVM.scaleValue)
.font(.title)
.foregroundColor(.green)
.animation(.easeOut(duration: 0.3), value: contentVM.scaleValue)
.onTapGesture {
contentVM.scaleValue = 1.5
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.3){
contentVM.scaleValue = 1.0
}
}
}
}
关于swift - 每当 SwiftUI 中的 Observed 属性发生变化时,动画 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75286301/