SwiftUI rotationEffect()内部动画异常行为,我无法将其禁用

问题描述 投票:0回答:1

我正在探索如何处理无限动画。我学习了如何启动它并尝试手动停止它。我发现最好的解决方案是计算动画属性的当前值,并在停止动画时进行设置。好吧,除了一会儿,它工作得很好。看起来rotationEffect()使用内置的自我动画来停止旋转。如果尝试立即开始和停止动画,则会遇到类似速度物理学的问题。类似于.spring动画,但我使用了.linear。我试图使用withAnimation(.none)禁用它,但是失败了。而且,如果您停止旋转接近90度(但小于90度),则会超出90度。解决此问题的唯一方法是使用CG框架构建自己的旋转修改器。

还有其他想法吗?

这里是代码:

import SwiftUI

class AnimationHandler: ObservableObject{
    @Published var isStarted: Bool = true
}

struct AnimationStopping: View {
    @ObservedObject var animationHandler = AnimationHandler()
    var body: some View {
        VStack{
            Spacer()
            AnimatedRectObservedObject(animationHandler: self.animationHandler)
            Spacer()
            Button(action: {
                self.animationHandler.isStarted.toggle()
            }){
                Text(self.animationHandler.isStarted ? "stop animation" : "start animation")
            }
        }
    }
}

struct AnimatedRectObservedObject: View{
    @State var startTime: Date = Date()
    @State var angle: Double = 0
    @ObservedObject var animationHandler: AnimationHandler
    var animation: Animation = Animation.linear(duration: 1).repeatForever(autoreverses: false)
    var body: some View{
       VStack{
            Rectangle()
                .fill(Color.green)
                .frame(width: 200, height: 200)
                .rotationEffect(Angle(degrees: angle))
                .animation(animationHandler.isStarted ? animation : .default)
            Spacer()
       }.onReceive(animationHandler.objectWillChange){
            let newValue = self.animationHandler.isStarted
            if newValue == false{
                 let timePassed = Date().timeIntervalSince(self.startTime)
                 let fullSecondsPassed = Double(Int(timePassed))
                 let currentStage = timePassed - fullSecondsPassed
                 let newAngle = self.angle - 90 + currentStage * 90
                withAnimation(.none){//not working:(((
                 self.angle = newAngle
                }
            }else {
                 self.startTime = Date()
                 self.angle += 90
             }
       }
       .onAppear{
            self.angle += 90
            self.startTime = Date()
        }
    }
}

更新:实际上,自定义修饰符将无济于事。我使用它,在上面打印,然后通过@ObservableObject来获取它的实际动画时间,然后观看:

current animation position 0.15000057220458984
current animation position 0.15833377838134766
current animation position 0.16666698455810547
current animation position 0.17500019073486328
current animation position 0.1833333969116211
current animation position 0.1916666030883789
current animation position 0.19999980926513672
current animation position 0.20833301544189453
animated from 0.0 to 1.0 stopped at 0.20833301544189453
current animation position 0.21662975207982527
current animation position 0.22470279080698674
current animation position 0.2323109631133775
current animation position 0.23920465996798157
current animation position 0.24513085941998725
current animation position 0.24984809499710536
current animation position 0.25314617272852047
current animation position 0.25487106971286266
current animation position 0.25495114064688096
current animation position 0.25341608746384736
current animation position 0.25040891469689086
current animation position 0.24617629182102974
current animation position 0.2410420152482402
current animation position 0.23537338342976
current animation position 0.2295457124710083
current animation position 0.2239141315640154
current animation position 0.21879699627515947
current animation position 0.2144686846222612
current animation position 0.2111600160587841
current animation position 0.20906241873944964
current animation position 0.20833301544189453
swift swiftui core-animation
1个回答
0
投票

答案很简单:

.animation(animationHandler.isStarted ? animation : .linear(duration: 0))
© www.soinside.com 2019 - 2024. All rights reserved.