我目前正在尝试使用 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:
关于SwiftUI EaseIn Transition 通过多种颜色循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68050505/