How can I create an animation color change from center of a view in SwiftUI? (please see the below gif)?
So far I have tried adding an animation modifier to the view (please see the below code), but am not quite sure how to make the animation start at the center of the screen and flow to the outer edges of the screen.
import SwiftUI
struct ContentView: View {
@State var color = Color.red
var body: some View {
VStack {
Button(action: {
color = .green
}, label: {
Text("change background color")
})
}
.frame(maxWidth: .infinity)
.frame(maxHeight: .infinity)
.background(color)
.animation(.default)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
There is probably more elegant way of doing this but it works.
struct AnimatedBackground: View {
@State var circleColor = Color.red
@State var height:CGFloat = 0
@State var backgroundColor: Color = .clear
@State var animation: Animation? = .default
var body: some View {
ZStack{
backgroundColor.ignoresSafeArea()
Circle()
.foregroundColor(circleColor)
.scaleEffect(CGSize(width: height, height: height))
VStack {
Button(action: {
animation = .default
circleColor = [Color.red, Color.orange, Color.green, Color.black, Color.gray, Color.white].randomElement()!
}, label: {
Text("change background color")
})
}
}.animation(animation)
.onChange(of: circleColor, perform: { value in
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: {timer in
height += 0.2
if height >= 3{
animation = nil
backgroundColor = circleColor
height = 0
timer.invalidate()
}
})
})
}
}
You can use two Circle
s in a ZStack
and animate the scale effect value of the top most circle.
struct ContentView: View {
private let colors: [Color] = [.red, .yellow, .blue, .pink, .orange]
private let maxScaleEffect: CGFloat = 4.0
private let minScaleEffect: CGFloat = 0
private let animationDuration = 0.6
private let animationDelay = 0.1
@State private var shouldTransition = true
@State private var colorIndex = 0
var body: some View {
ZStack {
Circle()
.fill(previousColor)
.scaleEffect(maxScaleEffect)
Circle()
.fill(transitioningColor)
.scaleEffect(shouldTransition ? maxScaleEffect : minScaleEffect)
Button("Change color") {
shouldTransition = false
colorIndex += 1
// Removing DispatchQueue here will cause the first transition not to work
DispatchQueue.main.asyncAfter(deadline: .now() + animationDelay) {
withAnimation(.easeInOut(duration: animationDuration)) {
shouldTransition = true
}
}
}
.foregroundColor(.primary)
}
}
private var previousColor: Color {
colors[colorIndex%colors.count]
}
private var transitioningColor: Color {
colors[(colorIndex+1)%colors.count]
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.