swift - 如何在 SwiftUI 中暂停动画?

标签 swift animation swiftui

我不知道如何在启动 withAnimation(_:) 方法后停止它。

我正在使用 SwiftUI 编写我的第一个应用程序,我想创建一个进度圈,它将由用户使用按钮控制 - 开始按钮,这将启动动画,其中圆圈将在最后未填充,停止按钮将有保存填充点的实际状态并停止动画。

我的主要观点:

struct MainView: View {
  @State private var fillPoint = 1.0 
  @State private var animationDuration = 10.0

  private var ring: Ring {
    let ring = Ring(fillPoint: self.fillPoint)
    return ring
  }

  var body: some View {
    VStack {
      ring.stroke(Color.red, lineWidth: 15.0)
        .frame(width: 200, height: 200)
        .padding(40)
      HStack {
        Button(action: {
          withAnimation(.easeIn(duration: self.animationDuration)) {
              self.fillPoint = 0
          }
        }) {
          Text("Start")
        }
        Button(action: {
          // what should I do here?
        }) {
          Text("Stop")
        }
      }
    }
  }
}

Ring 的结构:

struct Ring: Shape {
  var startArcAngle: Double = 360.0

  var fillPoint: Double {
    willSet {
      startArcAngle = 360 * newValue
    }
  }

  internal var animatableData: Double {
    get { return fillPoint }
    set { fillPoint = newValue }
  }

  internal func path(in rect: CGRect) -> Path {
    let endArcAngle = 0.0

    var path = Path()

    path.addArc(center: CGPoint(x: rect.size.width / 2,
                                y: rect.size.height / 2),
                radius: rect.size.width / 2,
                startAngle: .degrees(startArcAngle - 90),
                endAngle: .degrees(endArcAngle - 90),
                clockwise: true)

    return path
  }
}

我尝试操作animatableData值,但在Ring的结构之外它总是返回0.0(这是我的代码在动画启动时将在动画结束时实现的值)并且在Ring的结构内部它按照我想要的方式打印(0.96xxxx -> 0.94xxxx 等),但将其置于 Ring 结构之外总是返回 1.0 或 0.0。

最佳答案

看起来没有停止动画的控件。

由于您的要求是在进度中开始和停止绘制,因此一种替代解决方案是使用计时器。棘手的一点是根据计时器持续时间清除电弧。

这是我在 MainView 中更改的代码:

注意:根据您的选择调整动画持续时间。

struct MainView: View {
    @State private var fillPoint = 1.0
    @State private var animationDuration = 10.0
    @State private var  stopAnimation = true
    @State private var countdownTimer: Timer?
    
    private var ring: Ring {
        let ring = Ring(fillPoint: self.fillPoint)
        return ring
    }
    
    var body: some View {
        VStack {
            ring.stroke(Color.red, lineWidth: 15.0)
                .frame(width: 200, height: 200)
                .padding(40)
                .animation(self.stopAnimation ? nil : .easeIn(duration: 0.1))
            HStack {
                Button(action: {
                    self.stopAnimation = false
                    self.countdownTimer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
                        guard self.animationDuration > 0 else {
                            self.countdownTimer?.invalidate()
                            return
                        }
                        self.fillPoint = self.animationDuration/10
                        self.animationDuration -= 0.1
                    })
                }) {
                    Text("Start")
                }
                Button(action: {
                    self.countdownTimer?.invalidate()
                    self.stopAnimation = true
                }) {
                    Text("Stop")
                }
            }
        }
    }
}

关于swift - 如何在 SwiftUI 中暂停动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58041676/

相关文章:

ios - 有没有办法关闭 Xcode 8 的图像名称自动完成功能?

ios - 如何查看一个字符串是否与另一个字符串中的任何字符匹配?

javascript - JavaScript 中本地定义的样式和动画

html - CSS3 翻转动画

swift - 如何控制 SwiftUI 图像的无障碍画外音文本

swift - @IBInspectable var 是在哪个阶段设置的值

ios - 如何快速将 Int 转换为 int?

javascript - IE8/9 中的 CSS3 动画

swiftui - 如何在 SwiftUI NavigationLink 中移除不透明动画

navigation - 如何在 SwiftUI 中使用带有条件检查的按钮进行导航