更改反向动画速度SwiftUI

sc4hvdpw  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(106)

有没有办法改变反转动画的速度,使它快速反转,然后回到原来的速度?我用的是这样的动画。

static private let backgroundAnimation = Animation
        .linear(duration: time)
        .delay(1.0)
        .repeatForever(autoreverses: true)

谢谢!

flseospp

flseospp1#

如果SwiftUI没有提供加速反向动画的选项,那么可以通过应用自己的Animatable视图修改器来实现。您需要通过应用.repeatForever(autoreverses: false)来禁用内置的反向动画。然后将动画的反转部分实现为“前进”动画的尾端。
下面是一个例子:

struct OffsetModifier: ViewModifier, Animatable {

    private let maxOffset: CGFloat
    private let rewindSpeedFactor: Int
    private var progress: CGFloat

    // The progress value at which rewind begins
    private let rewindThreshold: CGFloat

    init(
        maxOffset: CGFloat,
        rewindSpeedFactor: Int = 4,
        progress: CGFloat
    ) {
        self.maxOffset = maxOffset
        self.rewindSpeedFactor = rewindSpeedFactor
        self.progress = progress

        // Compute the threshold at which rewind begins
        self.rewindThreshold = CGFloat(1) - (CGFloat(1) / CGFloat(rewindSpeedFactor + 1))
    }

    /// Implementation of protocol property
    var animatableData: CGFloat {
        get { progress }
        set { progress = newValue }
    }

    var xOffset: CGFloat {
        let fraction: CGFloat
        if progress > rewindThreshold {
            fraction = rewindThreshold - ((progress - rewindThreshold) * CGFloat(rewindSpeedFactor))
        } else {
            fraction = progress
        }
        return (fraction / rewindThreshold) * maxOffset
    }

    func body(content: Content) -> some View {
        content.offset(x: xOffset)
    }
}

struct ContentView: View {

    private let diameter = CGFloat(30)
    @State private var progress = CGFloat.zero

    var body: some View {
        VStack {
            GeometryReader { proxy in
                Circle()
                    .fill()
                    .foregroundColor(.red)
                    .frame(width: diameter, height: diameter)
                    .modifier(OffsetModifier(maxOffset: proxy.size.width - diameter, progress: progress))
                    .animation(.linear(duration: 3.0).repeatForever(autoreverses: false), value: progress)
            }
            .frame(height: diameter)
            .onAppear { progress = 1.0 }
        }
    }
}

相关问题