swift 设置数字计数器效果的动画-动画不平滑

wn9m85ua  于 2023-03-22  发布在  Swift
关注(0)|答案(1)|浏览(168)

我有一些UI,它需要一个数字从0开始,然后计数到指定的最大整数。下面是基本的动画:

为此,我创建了以下视图:

public struct AnimatableNumber: View {
    @State private var animatedValue: CGFloat = 0

    let maxNumber: CGFloat
    let font: SwiftUI.Font
    let animationDuration: Double

    public init(maxNumber: CGFloat,
                font: SwiftUI.Font,
                animationDuration: Double = 2) {
        self.maxNumber = maxNumber
        self.font = font
        self.animationDuration = animationDuration
    }

    public var body: some View {
        Text("\(Int(maxNumber))")
            .font(font)
            .foregroundColor(.clear)
            .modifier(AnimatingNumberOverlay(number: animatedValue, font: font))
            .minimumScaleFactor(0.5)
            .fixedSize()
            .onAppear {
                withAnimation(Animation.easeInOut(duration: animationDuration)) {
                    animatedValue = maxNumber
                }
            }
    }
}

private struct AnimatingNumberOverlay: AnimatableModifier {
    var number: CGFloat = 0
    let font: SwiftUI.Font

    var animatableData: CGFloat {
        get {
            number
        }

        set {
            number = newValue
        }
    }

    func body(content: Content) -> some View {
        content.overlay(Text("\(Int(number))").font(font))
    }
}

它的声明简单如下:

AnimatableNumber(maxNumber: number, font: SwiftUI.Font((Style.font(.chronicle80))))

一般来说,它的工作,但相当经常的动画是不是在所有顺利。例如:

请注意这里它是如何动画到45,然后停止,然后直接到最大值。
这种行为是零星的,所以想知道我可以改变我的看法,以确保一个更平滑的动画一致。

pinkon5k

pinkon5k1#

您可以使用计时器来获得所需的效果。

func animate() {
    let interval = duration / Double(value)
    Timer.scheduledTimer(withTimeInterval: interval, repeats: true) { timer in
        tracker += 1
        if tracker == value {
            timer.invalidate()
        }
    }
}

你可以在onAppear()事件中调用它。

struct AnimateableNumber: View {
    let value: Int
    @State private var tracker = 0
    let duration = 0.5
    
    var body: some View  {
        Text("\(tracker)")
            .onAppear() {
                animate()
            }
    }
    
    func animate() {
        ...
    }
}

相关问题