0

此动画在第一次查看时按预期运行,但当应用退出然后进入(或者如果您离开屏幕并返回)时,时间会随机混乱。如何更改此代码以在离开屏幕并返回后保持动画时序一致?

可以通过退出并返回应用程序几次来重新创建错误。

正确的动画 几个应用退出并重新进入后

import SwiftUI

struct ExampleView: View {
@State var isAnimating: Bool = false

let timing =  4.0
let maxCounter: Int = 3

var body: some View {
    ZStack {
        Circle()
            .stroke(
                Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
            .scaleEffect(isAnimating ? 1.0 : 0.0)
            .animation(
                Animation.easeOut(duration: timing)
                .repeatForever(autoreverses: false)
                .delay(Double(0) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
        
        Circle()
            .stroke(
                Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
            .scaleEffect(isAnimating ? 1.0 : 0.0)
            .animation(
                Animation.easeOut(duration: timing)
                .repeatForever(autoreverses: false)
                .delay(Double(1) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
        Circle()
            .stroke(
                Color.blue.opacity(isAnimating ? 0.0 : 1.0),
                style: StrokeStyle(lineWidth: isAnimating ? 0.0 : 15.0))
            .scaleEffect(isAnimating ? 1.0 : 0.0)
            .animation(
                Animation.easeOut(duration: timing)
                .repeatForever(autoreverses: false)
                .delay(Double(2) * timing / Double(maxCounter) / Double(maxCounter)), value: isAnimating)
    }
    .frame(width: 200, height: 200, alignment: .center)
    .onAppear {
        isAnimating = true
    }
}
}
4

1 回答 1

1

这是一个正确的方法,它需要使用 DispatchQueue 和 scenePhase:

PS:我注意到 Xcode 对您的原始代码有很多抱怨!我重构了你的代码并解决了那些抱怨的问题。

struct ExampleView: View { 
    var body: some View {
        ZStack {
            CustomCircleAnimationView(delayValue: 0.0)
            CustomCircleAnimationView(delayValue: 1.0)
            CustomCircleAnimationView(delayValue: 2.0)
        }
        .frame(width: 200, height: 200)  
    }
}


struct CustomCircleAnimationView: View {
    
    @Environment(\.scenePhase) private var scenePhase
    
    let delay: Double
    private let timing: Double
    private let maxCounter: Double
    @State private var startAnimation: Bool = false
    
    init(timing: Double =  4.0, maxCounter: Double = 3.0, delayValue: Double) {
        self.timing = timing
        self.maxCounter = maxCounter
        self.delay = (delayValue*timing)/(maxCounter*maxCounter)
    }
    
    var body: some View { if (scenePhase == .active) { circle } }
    
    var circle: some View {
        
        return Circle()
            .stroke(Color.blue, style: StrokeStyle(lineWidth: startAnimation ? 0.001 : 15.0))
            .scaleEffect(startAnimation ? 1.0 : 0.001)
            .opacity(startAnimation ? 0.001 : 1.0)
            .onAppear { DispatchQueue.main.async { startAnimation = true } }
            .onDisappear { startAnimation = false }
            .animation(Animation.easeOut(duration: timing).repeatForever(autoreverses: false).delay(delay), value: startAnimation)
        
    }
}
于 2021-12-01T23:07:45.797 回答