I am attempting to create a ripple effect on a button, but the animated circles are going below the button, and the ZStack is not functioning as expected.
Expected Result
I want the outer two circles to be continuously going out of the central dark gray circle without any break like this animation
Current Result:
This is my code in XCode Preview it looking good but when I run it on simulator it not working then.
import SwiftUI
struct SwiftUIView: View {
@State var vpnIsActive = false
let delayArr = [0.0,0.5,1.0,1.5,2.0]
var body: some View {
VStack {
ZStack {
ForEach(1...4,id:\.self){i in
RippleEffect(vpnIsActive: $vpnIsActive, delay: delayArr[i])
}
Circle()
.fill(vpnIsActive ? Color("homeBlue") : Color("homeGray"))
.frame(width: Constants.width * 0.4, height: Constants.width * 0.4)
VStack {
Button {
vpnIsActive.toggle()
} label: {
Image("power")
}
Text(vpnIsActive ? "Tap to Disconnect" : "Tap to Connect")
.foregroundColor(.white)
}
}
.frame(width: Constants.width * 0.4, height: Constants.width * 0.4)
}
}
}
struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
SwiftUIView()
}
}
struct Constants{
static let height = UIScreen.main.bounds.height
static let width = UIScreen.main.bounds.width
}
struct RippleEffect:View{
@State private var scale = 1.0
@Binding var vpnIsActive:Bool
let delay :Double
var body: some View{
VStack{
Circle()
.fill(vpnIsActive ? LinearGradient(colors: [Color("homeBlue").opacity(0.5), Color("homeBlue").opacity(0.05)], startPoint: .top, endPoint: .bottom) : LinearGradient(colors: [Color("homeGray").opacity(0.8), Color("homeGray").opacity(0.1)], startPoint: .top, endPoint: .bottom))
.scaleEffect(scale)
.opacity(2 - scale)
.animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: false).delay(delay))
.onAppear {
scale = 2.5
}
}
.frame(width: Constants.width * 0.3, height: Constants.width * 0.3)
}
}