在SwiftUI中动画处于活动状态时,如何挤压胶囊

在SwiftUI中动画处于活动状态时,如何挤压胶囊,swift,swiftui,Swift,Swiftui,我有一个胶囊,可以改变它在屏幕上的位置。我想让胶囊两端都被挤压,但动画不允许我这样做,因为它以2个视图作为开始和结束,我只能控制左右变化的效果,所以挤压效果没有发挥作用的空间!我怎样才能做到这一点呢?就像苹果那样 快速而肮脏的代码,但根据@Zaphod的建议,试着使用一个面具,把你的胶囊放在面具后面。然后根据帧大小设置偏移动画 struct SnakeLoading: View { @State private var animating: Bool = true

我有一个胶囊,可以改变它在屏幕上的位置。我想让胶囊两端都被挤压,但动画不允许我这样做,因为它以2个视图作为开始和结束,我只能控制左右变化的效果,所以挤压效果没有发挥作用的空间!我怎样才能做到这一点呢?就像苹果那样


快速而肮脏的代码,但根据@Zaphod的建议,试着使用一个面具,把你的胶囊放在面具后面。然后根据帧大小设置偏移动画

struct SnakeLoading: View {
    @State
    private var animating: Bool = true
    
    private let height: CGFloat = 10
    private let capsuleWidth: CGFloat = 100
    
    func leadingOffset(size: CGSize) -> CGFloat {
        (-size.width - capsuleWidth) * 0.5 + height
    }
    
    func trailingOffset(size: CGSize) -> CGFloat {
        (size.width + capsuleWidth) * 0.5 - height
    }
    
    var body: some View {
        GeometryReader { geo in
            ZStack {
                // Background
                Rectangle()
                    .fill(Color.gray)
                // Capsule
                Capsule()
                    .fill(Color.green)
                    .offset(x: animating ? leadingOffset(size: geo.size) : trailingOffset(size: geo.size))
                    .frame(width: capsuleWidth, height: height)
                    .onAppear() { animating.toggle() }
                    .animation(Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true), value: animating)

            }
            .mask(Capsule()
                    .frame(height: height)
            )
        }
        .padding()
    }
}

难道你不能想象绿色胶囊在“后面”,在左右两边走得更远吗?这是个好办法,但我注意到我的代码和你的代码在方向改变上也有问题。是的,我担心会发生这种情况,正如我说的:又快又脏;)如果你们也能解决定向问题,我会很高兴的。如果你们能找到一种方法,谢谢。我会尽快尝试:)
struct SnakeLoading: View {
    @State
    private var animating: Bool = true
    
    private let height: CGFloat = 10
    private let capsuleWidth: CGFloat = 100
    
    func leadingOffset(size: CGSize) -> CGFloat {
        (-size.width - capsuleWidth) * 0.5 + height
    }
    
    func trailingOffset(size: CGSize) -> CGFloat {
        (size.width + capsuleWidth) * 0.5 - height
    }
    
    var body: some View {
        GeometryReader { geo in
            ZStack {
                // Background
                Rectangle()
                    .fill(Color.gray)
                // Capsule
                Capsule()
                    .fill(Color.green)
                    .offset(x: animating ? leadingOffset(size: geo.size) : trailingOffset(size: geo.size))
                    .frame(width: capsuleWidth, height: height)
                    .onAppear() { animating.toggle() }
                    .animation(Animation.easeInOut(duration: 1.0).repeatForever(autoreverses: true), value: animating)

            }
            .mask(Capsule()
                    .frame(height: height)
            )
        }
        .padding()
    }
}