[英]Crossfading Images in SwiftUI doesn't seem to work
I'd like to achieve an an animated background that crossfades a bunch of images in SwiftUI.我想实现一个动画背景,在 SwiftUI 中对一堆图像进行淡入淡出。
I've managed to get an array of Colors to crossfade nicely between them using the following code snippets, but if I replace the array of Colors with an array of Images the same approach doesn't work.我已经使用以下代码片段设法使一组颜色在它们之间很好地交叉淡入淡出,但是如果我用一组图像替换颜色数组,则相同的方法不起作用。 The images are replaced, but not animated.
图像被替换,但没有动画。 Yet both a Color and an Image are of type some View right?
然而 Color 和 Image 都属于 some View 类型,对吗?
The following works:以下工作:
struct ImageBackgroundView: View {
@State private var index = 0
private let colors:[Color] = [.red, .blue, .green, .orange, .pink, .black]
private let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
var body: some View {
colors[self.index]
.animation(.easeInOut(duration: 1))
.onReceive(timer) { _ in
print(self.index)
self.index += 1
if self.index > 5 { self.index = 0 }
}
}
but, if I replace the [Color] array with an array of type [Images], as follows, the images are transitioned, but the crossfade doesn't appear to work:但是,如果我用 [Images] 类型的数组替换 [Color] 数组,如下所示,图像会转换,但交叉淡入淡出似乎不起作用:
struct ImageBackgroundView: View {
@State private var index = 0
private let images = (1...8).map { Image("background\($0)") }
private let timer = Timer.publish(every: 5, on: .main, in: .common).autoconnect()
var body: some View {
images[self.index]
.animation(.easeInOut(duration: 1))
.onReceive(timer) { _ in
print(self.index)
self.index += 1
if self.index > 5 { self.index = 0 }
}
}
Can anyone shed any light on why this might be the case?任何人都可以解释为什么会这样吗? Is it just a bug in SwiftUI at the present time?
目前这只是 SwiftUI 中的一个错误吗?
I achieved a similar effect in a previous app using all sorts of addSubview calls animating the opacity of overlaying views - all sorts of stuff we shouldn't need to fiddle with in this brave new SwiftUI world right?我在以前的应用程序中使用各种 addSubview 调用实现了类似的效果,这些调用为覆盖视图的不透明度设置动画——在这个勇敢的新 SwiftUI 世界中,我们不需要摆弄各种东西,对吧?
This is interesting and it got me thinking.这很有趣,它让我思考。
You can use a flag, say show
.您可以使用标志,例如
show
。 And a ZStack
that holds your image
object.还有一个
ZStack
保存你的image
对象。 And then use transition
combined with animation
you want in that image
.然后在该
image
使用transition
与您想要的animation
相结合。
But, only do that if show
is true
.但是,只有在
show
为true
时才这样做。
Attach the .onReceive
event to the ZStack
instead of your image
.将
.onReceive
事件附加到ZStack
而不是您的image
。 In that event, toggle the flag show
.在这种情况下,切换标志
show
。
@State private var index = 0
@State private var show = true
private let images = (1...8).map { Image("background\($0)") }
private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
ZStack {
if self.show {
images[self.index]
.transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
}
}.onReceive(timer) { _ in
print(self.index)
self.index += 1
self.show.toggle()
if self.index > 4 { self.index = 0 }
}
}
Voila!瞧!
Also, as far as I know, Color
is not a View
.另外,据我所知,
Color
不是View
。
A Color is a late-binding token: SwiftUI only resolves it to a concrete value just before using it in a given environment.
Color 是后期绑定令牌:SwiftUI 仅在给定环境中使用它之前将其解析为具体值。
ref: https://developer.apple.com/documentation/swiftui/color参考: https : //developer.apple.com/documentation/swiftui/color
I changed your example a little and now background images changed with animation.我稍微改变了你的例子,现在背景图像随着动画而改变。 But I can't suggest, why the same things don't work either for
Color
or for Image
.但我不能建议,为什么同样的事情对
Color
或Image
不起作用。 So, here is my working example, maybe it will push you in right direction:所以,这是我的工作示例,也许它会将您推向正确的方向:
struct AnimatedBackground: View {
@State private var index = 0
private let images: [Image] = ["trash", "star", "circle", "circle.fill", "square", "cloud"].map{ Image(systemName: $0) }
private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
var body: some View {
ZStack {
ForEach(images.indices, id: \.self) { imageIndex in
self.images[imageIndex]
.resizable()
.transition(.opacity)
.opacity(imageIndex == self.index ? 1 : 0)
}
}
.onReceive(timer) { _ in
withAnimation {
self.index = self.index < self.images.count - 1 ? self.index + 1 : 0
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.