SwiftUI EaseIn Transition 通过多种颜色循环

标签 swift xcode animation colors swiftui

我目前正在尝试使用 SwiftUI 创建动画以在多种颜色之间转换,但是,我遇到了一个特定问题。该代码可以工作,但是,它只会改变大约 2-3 种不同的颜色,然后重置回原始颜色。我还通过 GitHub 使用名为“DynamicColor”的库作为将十六进制代码轻松转换为 SwiftUI Color 变量的方法.

下面是我定义的 @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])
                
     }
  }
}

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

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

我尝试简单地一个接一个地重新分配“self.bgColor”变量,但结果相同。我也搞乱了动画的持续时间,但同样没有运气。不管怎样,如果有人碰巧知道我可能做错了什么,我真的很感激你的帮助。非常感谢您,希望大家度过愉快的一天!

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

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:

Short clip demonstrating part of the animation

关于SwiftUI EaseIn Transition 通过多种颜色循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68050505/

相关文章:

swift - 命令行工具 Xcode 的控制台中没有打印任何内容

ios - 如何从 TableView 中删除特定数据

ios - 如何在 Swift 中从 Health Kit Sdk 获取卡路里和心率?

iphone - 跟踪选定的单元格

iphone - appendFormat 泄漏

objective-c - 无法从 objective-c、Xcode 8 访问 Swift 变量

css - 我想同时淡入和旋转

javascript - 更改 2 个元素的不透明度以产生交叉淡入淡出效果

ios - UIImage 方向 Swift

css - 动画封面背景从比例 : 0. 8 到比例:1 - 保持 100% 宽度+高度