gpt4 book ai didi

SwiftUI 暂停/恢复旋转动画

转载 作者:行者123 更新时间:2023-12-03 23:34:21 41 4
gpt4 key购买 nike

到目前为止,我已经看到了以下停止动画的技术,但我在这里寻找的是旋转 View 停止在当前的角度,而不是返回到 0。

struct DemoView: View {
@State private var isRotating: Bool = false
var foreverAnimation: Animation {
Animation.linear(duration: 1.8)
.repeatForever(autoreverses: false)
}
var body: some View {
Button(action: {
self.isRotating.toggle()
}, label: {
Text("🐰").font(.largeTitle)
.rotationEffect(Angle(degrees: isRotating ? 360 : 0))
.animation(isRotating ? foreverAnimation : .linear(duration: 0))
})
}
}
似乎旋转角度为 360 或 0 并不能让我将其卡住在中间角度(并最终从那里恢复)。有任何想法吗?

最佳答案

在 SwiftUI 中暂停和恢复动画非常简单,您只需在 withAnimation 中确定动画类型即可。堵塞。
您缺少的是另外两条信息:

  • 动画暂停的值是多少?
  • 动画在恢复时应该继续的值是多少?

  • 这两部分至关重要,因为请记住,SwiftUI View 只是表达您希望 UI 外观的方式,它们只是声明。除非您自己提供更新机制,否则它们不会保持 UI 的当前状态。所以 UI 的状态(比如当前的旋转角度)不会自动保存在其中。
    虽然您可以引入计时器并以 X 毫秒的谨慎步长自己计算角度值,但没有必要这样做。我建议宁愿让系统以合适的方式计算角度值。
    您唯一需要的是收到有关该值的通知,以便您可以存储它并用于在暂停后设置正确的角度并计算恢复的正确目标角度。有几种方法可以做到这一点,我真的鼓励您阅读 SwiftUI 动画的 3 部分介绍,地址为 https://swiftui-lab.com/swiftui-animations-part1/。 .
    您可以采取的一种方法是使用 GeometryEffect .它允许您指定变换和旋转是基本变换之一,因此它非常适合。它还遵守 Animatable协议(protocol)让我们可以轻松参与到 SwiftUI 的动画系统中。
    重要的部分是让 View 知道当前的旋转状态是什么,以便它知道我们应该保持暂停的角度以及恢复时应该转到的角度。这可以通过一个简单的绑定(bind)来完成,该绑定(bind)专门用于报告 GeometryEffect 中的中间值。到 View 。
    显示工作解决方案的示例代码:
    import SwiftUI

    struct PausableRotation: GeometryEffect {

    // this binding is used to inform the view about the current, system-computed angle value
    @Binding var currentAngle: CGFloat
    private var currentAngleValue: CGFloat = 0.0

    // this tells the system what property should it interpolate and update with the intermediate values it computed
    var animatableData: CGFloat {
    get { currentAngleValue }
    set { currentAngleValue = newValue }
    }

    init(desiredAngle: CGFloat, currentAngle: Binding<CGFloat>) {
    self.currentAngleValue = desiredAngle
    self._currentAngle = currentAngle
    }

    // this is the transform that defines the rotation
    func effectValue(size: CGSize) -> ProjectionTransform {

    // this is the heart of the solution:
    // reporting the current (system-computed) angle value back to the view
    //
    // thanks to that the view knows the pause position of the animation
    // and where to start when the animation resumes
    //
    // notice that reporting MUST be done in the dispatch main async block to avoid modifying state during view update
    // (because currentAngle is a view state and each change on it will cause the update pass in the SwiftUI)
    DispatchQueue.main.async {
    self.currentAngle = currentAngleValue
    }

    // here I compute the transform itself
    let xOffset = size.width / 2
    let yOffset = size.height / 2
    let transform = CGAffineTransform(translationX: xOffset, y: yOffset)
    .rotated(by: currentAngleValue)
    .translatedBy(x: -xOffset, y: -yOffset)
    return ProjectionTransform(transform)
    }
    }

    struct DemoView: View {
    @State private var isRotating: Bool = false

    // this state keeps the final value of angle (aka value when animation finishes)
    @State private var desiredAngle: CGFloat = 0.0

    // this state keeps the current, intermediate value of angle (reported to the view by the GeometryEffect)
    @State private var currentAngle: CGFloat = 0.0

    var foreverAnimation: Animation {
    Animation.linear(duration: 1.8)
    .repeatForever(autoreverses: false)
    }

    var body: some View {
    Button(action: {
    self.isRotating.toggle()
    // normalize the angle so that we're not in the tens or hundreds of radians
    let startAngle = currentAngle.truncatingRemainder(dividingBy: CGFloat.pi * 2)
    // if rotating, the final value should be one full circle furter
    // if not rotating, the final value is just the current value
    let angleDelta = isRotating ? CGFloat.pi * 2 : 0.0
    withAnimation(isRotating ? foreverAnimation : .linear(duration: 0)) {
    self.desiredAngle = startAngle + angleDelta
    }
    }, label: {
    Text("🐰")
    .font(.largeTitle)
    .modifier(PausableRotation(desiredAngle: desiredAngle, currentAngle: $currentAngle))
    })
    }
    }

    关于SwiftUI 暂停/恢复旋转动画,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62648245/

    41 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com