有没有更好的方法在 swiftui 中实现抖动动画?

Posted

技术标签:

【中文标题】有没有更好的方法在 swiftui 中实现抖动动画?【英文标题】:Is there a better way to implement a shake animation in swiftui? 【发布时间】:2020-05-05 17:16:54 【问题描述】:

当用户尝试登录而不填写所有文本字段时,我试图让一个按钮抖动,这就是我到目前为止遇到的情况:

struct Shake: GeometryEffect 
    var amount: CGFloat = 10
    var shakesPerUnit = 3
    var animatableData: CGFloat

    func effectValue(size: CGSize) -> ProjectionTransform 
        ProjectionTransform(CGAffineTransform(translationX:
            amount * sin(animatableData * .pi * CGFloat(shakesPerUnit)),
            y: 0))
    


struct Correct: View 
    @State var attempts: Int = 0

    var body: some View 
        VStack 
            Rectangle()
                .fill(Color.pink)
                .frame(width: 200, height: 100)
                .modifier(Shake(animatableData: CGFloat(attempts)))
            Spacer()
            Button(action: 
                withAnimation(.default) 
                    self.attempts += 1
                

            , label:  Text("Login") )
        
    

但是,这对于按钮来说特别无用,即使这样,动画也显得非常不正常,因为它非常机器人化。有人可以提出改进建议以便我可以摇动我的按钮吗?

【问题讨论】:

【参考方案1】:

试试这个

struct ContentView: View 
    @State var selected = false

    var body: some View 
        VStack 
            Button(action: 
                self.selected.toggle()
            )  selected ? Text("Deselect") : Text("Select") 
            Rectangle()
                .fill(Color.purple)
                .frame(width: 200, height: 200)
                .offset(x: selected ? -30 : 0)
                .animation(Animation.default.repeatCount(5).speed(6))
        
    

【讨论】:

这很好,但动画完成后它不会重置Rectangle()offset。可以在此处找到执行此操作的示例:objc.io/blog/2019/10/01/swiftui-shake-animation【参考方案2】:

我这样做是为了让场地震动,然后回到原来的位置:

private func signUp() 
        if email.isEmpty 
            withAnimation 
                emailIsWrong = true
            
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) 
                withAnimation 
                    emailIsWrong = false
                
            
            return
        

其中emailIsWrong 是@State 变量:

@State private var emailIsWrong = false

基本上在 0.2 秒后,我将 emailIsWrong 改回 false,以便视图回到原来的位置。我的文本字段如下所示:

 TextField("Email", text: $email)
    .padding()
    .frame(height: 45)
    .background(Color.white)   
    .colorScheme(.light)
    .offset(x: emailIsWrong ? -8 : 0)
    .animation(Animation.default.repeatCount(3, autoreverses: true).speed(6))

【讨论】:

以上是关于有没有更好的方法在 swiftui 中实现抖动动画?的主要内容,如果未能解决你的问题,请参考以下文章

在 SwiftUI 中实现昂贵的派生属性的最佳方法是啥?

Swift中实现用户输入防抖动的两种方法

Swift中实现用户输入防抖动的两种方法

如何在 SwiftUI 中制作“显示”式的折叠/展开动画?

使用特定调色板在 C# 中实现 Floyd-Steinberg 抖动

SwiftUI 动画:如何延迟重复动画