【问题标题】:how to do a simple scaling animation and why isn't this working?如何做一个简单的缩放动画,为什么这不起作用?
【发布时间】:2020-04-03 13:32:37
【问题描述】:

我刚刚在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)
        }
    }
}

【问题讨论】:

    标签: animation swiftui


    【解决方案1】:

    这是可能的方法(基于AnimatableModifier)。实际上,它演示了如何检测当前动画结束并执行某些操作 - 在这种情况下,对于您的缩放场景,只需启动反转。

    使用 Xcode 11.4 / iOS 13.4 测试

    简化和修改您的示例

    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
            }
        }
    }
    

    实际上,这里的节目制作人...重要的 cmets inline。

    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)
        }
    }
    

    【讨论】:

    • 在 ViewModifier 中使用 ReversingScale 时出现以下错误。 Modifying state during view update, this will cause undefined behavior.。你有什么想法吗?
    • @schinj:Asperi 展示的方式是个好方法,您需要使用 DispatchQueue 设置值以及一个小的 deadLine,然后它可以解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 2011-10-25
    • 2012-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多