SwiftUI EaseIn 过渡通过多种颜色循环

SwiftUI EaseIn Transition Cycling Through Multiple Colors

我目前正在尝试使用 SwiftUI 创建动画以在多种颜色之间转换,但是,我遇到了一个特定问题。该代码有效,但是,它只改变了 2-3 种不同的颜色,然后重置回原来的 color.I 我还使用一个名为 'DynamicColor' 到 GitHub 的库作为一种轻松转换的方式SwiftUI 颜色变量的十六进制代码。

下面是我定义的保存当前颜色的@State 变量。它还显示了 UInt64 数字数组,其中包含我想要循环显示的所有颜色。

//Initialize the Color variable to the first color on the DesignMatters transition

@State private var bgColor = Color(hex: 0x67C7C7)

//Array of colors that I'd like to cycle through

let colorArray:[UInt64] = [0x65CCC2, 0x6EC6B2, 0x75AA89, 0x83B88A, 0x8BB37E, 0x9EA77E, 0xB0987A, 0xC18F77, 0xD28274, 0xE27771, 0xEC6E72, 0xE17180, 0xD5758E, 0xC9769D, 0xBD79AC, 0xB07BBD, 0xA280CD, 0x9687D5, 0x8E93D2, 0x849FD0, 0x7BADCD, 0x71B9CB, 0x66C8C7, 0x65CCBE, 0x6BC8B3, 0x75C1A4, 0x7CBC96, 0x83B98B, 0x8BB37E, 0x9EA67B, 0xAF9979, 0xC28D77, 0xD28275, 0xE47872, 0xEB6E75, 0xDD7284, 0xCE7696, 0xC078A5, 0xB47BB7, 0xA67FC8, 0x9B80D6, 0x908DD3, 0x879CD1, 0x7DA7CD, 0x73B6CC]

我创建的动画函数如下所示:

//Function to transition between colors in the background
func backgroundColorAnimation () {

    var count = 0
    withAnimation(.easeIn(duration: 1).repeatForever(autoreverses: false)) {
    
    //increment the counter
    count += 1
            
    //check if counter is within bounds of the array
    if (count < colorArray.count) {
                
        self.bgColor = Color(hex: colorArray[count])
                
     }
  }
}

最后,这是实际显示动画的视图主体:

var body: some View {
        
    ZStack {
            
        Rectangle()
            .opacity(0)
            
        Text("Hello World!")
            
     }
     .background(bgColor)
     .frame(width:500, height: 350)
     .onAppear {
           
         backgroundColorAnimation()
           
     }
}

我试图简单地一个接一个地重新分配“self.bgColor”变量,结果相同。我也搞砸了动画的持续时间,但同样没有运气。无论如何,如果有人碰巧知道我可能做错了什么,我将非常感谢您的帮助。非常感谢,希望大家今天过得愉快!

(UPDATE) 在查看我发布的代码时,无论出于何种原因,UInt64 变量数组的计数返回 1。只是为了澄清我的另一种方式已经解决了这个问题,我已经包含了视图的主体,我只是在其中一个接一个地更改变量:

ZStack {
            
  Rectangle()
     .opacity(0)
            
  Text("Hello World!")
            
}
.background(bgColor)
.frame(width:500, height: 350)
.onAppear {
            
    withAnimation(.easeIn(duration: 1).repeatForever(autoreverses: true)) {
               
                self.bgColor = Color(hex: 0x67C7C7)
                self.bgColor = Color(hex: 0x65CCC2)
                self.bgColor = Color(hex: 0x6EC6B2)
                self.bgColor = Color(hex: 0x75AA89)
                self.bgColor = Color(hex: 0x83B88A)
                self.bgColor = Color(hex: 0x8BB37E)
                self.bgColor = Color(hex: 0x9EA77E)
                self.bgColor = Color(hex: 0xB0987A)
                self.bgColor = Color(hex: 0xC18F77)
                self.bgColor = Color(hex: 0xD28274)
                self.bgColor = Color(hex: 0xE27771)
                self.bgColor = Color(hex: 0xEC6E72)
                self.bgColor = Color(hex: 0xE17180)
                self.bgColor = Color(hex: 0xD5758E)
                self.bgColor = Color(hex: 0xC9769D)
                self.bgColor = Color(hex: 0xBD79AC)
                self.bgColor = Color(hex: 0xB07BBD)
                self.bgColor = Color(hex: 0xA280CD)
                self.bgColor = Color(hex: 0x9687D5)
                self.bgColor = Color(hex: 0x8E93D2)
                self.bgColor = Color(hex: 0x849FD0)
                self.bgColor = Color(hex: 0x7BADCD)
                self.bgColor = Color(hex: 0x71B9CB)
                self.bgColor = Color(hex: 0x66C8C7)
                self.bgColor = Color(hex: 0x65CCBE)
                self.bgColor = Color(hex: 0x6BC8B3)
                self.bgColor = Color(hex: 0x75C1A4)
                self.bgColor = Color(hex: 0x7CBC96)
                self.bgColor = Color(hex: 0x83B98B)
                self.bgColor = Color(hex: 0x8BB37E)
                self.bgColor = Color(hex: 0x9EA67B)
                self.bgColor = Color(hex: 0xAF9979)
                self.bgColor = Color(hex: 0xC28D77)
                self.bgColor = Color(hex: 0xD28275)
                self.bgColor = Color(hex: 0xE47872)
                self.bgColor = Color(hex: 0xEB6E75)
                self.bgColor = Color(hex: 0xDD7284)
                self.bgColor = Color(hex: 0xCE7696)
                self.bgColor = Color(hex: 0xC078A5)
                self.bgColor = Color(hex: 0xB47BB7)
                self.bgColor = Color(hex: 0xA67FC8)
                self.bgColor = Color(hex: 0x9B80D6)
                self.bgColor = Color(hex: 0x908DD3)
                self.bgColor = Color(hex: 0x879CD1)
                self.bgColor = Color(hex: 0x7DA7CD)
                self.bgColor = Color(hex: 0x73B6CC)
                
            }
           
        }

此解决方案不使用一个动画,而是使用每秒发送更新的计时器。

我对 SwiftUI 还很陌生,所以我不太确定这是否是最好的解决方案。

不过,我找到了使用计时器的解决方法。这是我的代码:

struct ColorChangeAnimation: View {
    
    @State private var bgColor = Color(hex: 0x67C7C7)
    @State private var bgColorIndex = 0
    @State var colorArray:[UInt64] = [0x65CCC2, 0x6EC6B2, 0x75AA89, 0x83B88A, 0x8BB37E, 0x9EA77E, 0xB0987A, 0xC18F77, 0xD28274, 0xE27771, 0xEC6E72, 0xE17180, 0xD5758E, 0xC9769D, 0xBD79AC, 0xB07BBD, 0xA280CD, 0x9687D5, 0x8E93D2, 0x849FD0, 0x7BADCD, 0x71B9CB, 0x66C8C7, 0x65CCBE, 0x6BC8B3, 0x75C1A4, 0x7CBC96, 0x83B98B, 0x8BB37E, 0x9EA67B, 0xAF9979, 0xC28D77, 0xD28275, 0xE47872, 0xEB6E75, 0xDD7284, 0xCE7696, 0xC078A5, 0xB47BB7, 0xA67FC8, 0x9B80D6, 0x908DD3, 0x879CD1, 0x7DA7CD, 0x73B6CC]
    
    @State private var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    
    var body: some View {
        
        Rectangle()
            .ignoresSafeArea()
            .foregroundColor(Color(hex:  UInt(colorArray[bgColorIndex])))
            .onReceive(timer) { _ in
                
                if bgColorIndex == colorArray.count - 1 {
                    timer.upstream.connect().cancel()
                    
                    DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                        withAnimation(.easeIn(duration: 1)) { self.bgColorIndex = 0 }
                        timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
                    }
                    
                } else {
                    withAnimation(.easeIn(duration: 1)) { self.bgColorIndex += 1 }
                }
            }
    }
}

说明

一开始我声明了一个新的 @State 变量来跟踪 colorArray 的当前索引。然后我使用 .onAppear(perform: //code) 修饰符每秒将索引加 1。

我添加了一些代码,当计时器到达数组顶部时断开计时器。然后我添加 1 秒延迟,然后将数组设置回 0。这是为了确保索引始终保持在范围内,并且每种颜色都有 1 秒的显示时间。

同样,不太确定这是否是最佳解决方案,但它确实有效!

工作项目的 GIF: