【问题标题】:How can I pause a repeatForever Animation and the resume it in SwiftUI?如何在 SwiftUI 中暂停 repeatForever 动画并恢复它?
【发布时间】:2021-12-26 18:48:23
【问题描述】:

我有一个 repeatForever 动画,我想暂停动画,然后再恢复它,但我的代码不起作用,它们破坏了当前动画的帧。

 struct HatchedShap: Shape {
    let dis: CGFloat
    var move: CGFloat

    var animatableData: CGFloat {
        get { return move }
        set { move = newValue }
    }

    func path(in rect: CGRect) -> Path {
        
        Path { path in
            
            for start in stride(from: 0, through: rect.height, by: dis) {
                
                let offset = start + (dis*move).truncatingRemainder(dividingBy: dis)

                if (0.0...rect.height ~= offset) {
                    path.move(to: CGPoint(x: rect.minX, y: rect.minY + offset))
                    path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + offset))
                }

            }
        }
    }
}

用例:

struct ContentView: View {
    
    @State private var move: CGFloat = 0.0
    
    var body: some View {
        
        HStack {
            
            VStack {
                
                Text(String(describing: move)).bold().animation(.none)
                
                HatchedShap(dis: 30.0, move: move)
                    .stroke(Color.red, style: StrokeStyle(lineWidth: 5.0))
                    .background(Color.black)
                    .frame(width: 100, height: 200)
                    .onTapGesture {
                        if (move == 3) { move = 0}
                        else { move = 3 }
                    }
            }
            .animation((move != 0) ? Animation.linear(duration: 1.0).repeatForever(autoreverses: false) : Animation.linear(duration: 1.0), value: move)
            
        }
    }
}

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    我不知道为什么,但是你的形状不喜欢 move 值来回改变。即使删除动画的三元组,当您再次将其从 3 更改为 0 到 3 时,动画也会卡顿。

    我提出了两个同步渲染的视图,一个是动画的,一个不是。只需使用相反的.opacity,这样当一个可见时,另一个是透明的。您会注意到move.onAppear() 第一次更改以启动动画后并没有更改。点击 Gif 查看输出:

    struct ContentView: View {
        @State private var move: CGFloat = 0
        @State var pause = false
        
        var body: some View {
            
            HStack {
                VStack {
                    Text(String(describing: move)).bold().animation(.none)
                    
                    HatchedShap(dis: 30.0, move: move)
                        .stroke(Color.red, style: StrokeStyle(lineWidth: 5.0))
                        .animation(Animation.linear(duration: 1.0).repeatForever(autoreverses: false), value: move)
                        .opacity(!pause ? 1 : 0)
                        // This is the paused view
                        .overlay(HatchedShap(dis: 30.0, move: move)
                                    .stroke(Color.red, style: StrokeStyle(lineWidth: 5.0))
                                    .opacity(pause ? 1 : 0)
                        )
                        .background(Color.black)
                        .frame(width: 100, height: 200)
                        .onTapGesture {
                            pause.toggle()
                        }
                        .onAppear {
                            move = 3
                        }
                }
            }
        }
    }
    

    话虽如此,我不知道为什么当move 多次切换时,形状的动画会出现口吃。这值得研究。

    【讨论】:

    • 但是您是否阅读了我正在寻找暂停和恢复的问题?你也运行了我的代码吗?我的代码比您当前的答案更好,因为您出于未知原因混合了 2 HatchedShap,但毕竟您的代码没有提供暂停和恢复目标!那么你想在这里回答什么?另外我想说的是,使用opacity 进行非常糟糕的编码动画将在不透明度为零的情况下暂停运行!在暂停中,移动值变为零!这也显示了错误的方法。移动值可能在 0...3 之间,具体取决于用户点击的时间!
    • 我确实运行了你的代码。这就是我想出的理解,即您的形状在停止和开始时动画效果不佳。我相信你在测试中注意到了这一点。如果您注意到,.overlay 上没有动画,因此move 的值无关紧要。此外,SwiftUI 非常擅长确定需要更新的内容。透明视图不需要更新,因此它“运行”的事实并没有使用资源。动画会为用户暂停,只是不是以您想要的方式。
    • 尊重您和您的时间,您的答案不是我所期待的,我认为您的答案甚至不接近正确答案。 :) 但再次感谢。 ;) PS:您说:“透明视图不需要更新”这不是真的!自己重新检查一下。视图是关于它的不透明度的视图,它将使用 cpu 资源。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 1970-01-01
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多