SwiftUI如何在动画反转状态时避免使用delay()?

huangapple go评论72阅读模式
英文:

SwiftUI how to avoid delay() during the reversing state of an animation?

问题

我想使用SwiftUI实现一个简单的加载动画。动画逻辑如下:

1. 放大第一个圆,然后将其恢复到原始大小。
2. 放大第二个圆,然后将其恢复到原始大小。
3. 放大第三个圆,然后将其恢复到原始大小。
4. 无限重复步骤1-3

然而,我注意到如果我在repeatForever(autoreverses: true)中使用delay(),在动画播放反向时会出现不必要的延迟。我该如何避免在反向动画期间出现这种延迟?
英文:

I want to implement a simple loading animation using SwiftUI. The animation logic is as follows:

  1. Enlarge the first circle, then return it to its original size.
  2. Enlarge the second circle, then return it to its original size.
  3. Enlarge the third circle, then return it to its original size.
  4. Repeat steps 1-3 indefinitely.

However, I have noticed that if I use repeatForever(autoreverses: true) with delay(), there is an unwanted delay when the animation is played in reverse. How can I avoid this delay during the reverse animation?

import SwiftUI

struct AnimationView: View {
    @State private var scale: CGFloat = 1.0
    @State var animate = false
    
    var body: some View {
        HStack {
            Circle()
                .scaleEffect(scale)
                .frame(width: 20, height: 20)
                .animation(Animation.easeInOut(duration: 1.0).delay(0).repeatForever(autoreverses: true), value: animate)
            Circle()
                .scaleEffect(scale)
                .frame(width: 20, height: 20)
                .animation(Animation.easeInOut(duration: 1.0).delay(1).repeatForever(autoreverses: true), value: animate)
            Circle()
                .scaleEffect(scale)
                .frame(width: 20, height: 20)
                .animation(Animation.easeInOut(duration: 1.0).delay(2).repeatForever(autoreverses: true), value: animate)
        }
        .frame(width: 400, height: 400)
        .onAppear {
            animate = true
            scale = 1.2
        }
    }
}



struct AnimationView_Previews: PreviewProvider {
    static var previews: some View {
        AnimationView()
    }
}

答案1

得分: 2

只需要将 .delay() 放在 repeatForever 后面

.repeatForever(autoreverses: true).delay(2)

还可以改进以避免代码重复

struct AnimationView: View {
    @State private var scale: CGFloat = 1.0
    @State var animate = false
    
    let startTimes: [Double] = [1, 1.5, 2] // 每个圆形动画的开始时间
    
    var body: some View {
        HStack {
            ForEach(0..<startTimes.count, id: \.self) { index in
                Circle()
                    .scaleEffect(scale)
                    .frame(width: 20, height: 20)
                    .animation(Animation.easeInOut(duration: 1.0)
                        .repeatForever(autoreverses: true)
                        .delay(startTimes[index]), value: animate)
            }
        }
        .frame(width: 400, height: 400)
        .onAppear {
            animate = true
            scale = 1.2
        }
    }
}
英文:

You just need to move .delay() after repeatForever

.repeatForever(autoreverses: true).delay(2)

also you can improve to avoid code duplication

struct AnimationView: View {
@State private var scale: CGFloat = 1.0
@State var animate = false

let startTimes: [Double] = [1, 1.5, 2] // Start times for each circle animation

var body: some View {
    HStack {
        ForEach(0..&lt;startTimes.count, id: \.self) { index in
            Circle()
                .scaleEffect(scale)
                .frame(width: 20, height: 20)
                .animation(Animation.easeInOut(duration: 1.0)
                    .repeatForever(autoreverses: true)
                    .delay(startTimes[index]), value: animate)
        }
    }
    .frame(width: 400, height: 400)
    .onAppear {
        animate = true
        scale = 1.2
    }
} }

huangapple
  • 本文由 发表于 2023年5月25日 19:46:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76331917.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定