I have created a circle in swiftUI, and I want to fill it with sine wave animation for the water wave effect/animation. I wanted to fill it with a similar look:
Below is my code:
import SwiftUI
struct CircleWaveView: View {
var body: some View {
Circle()
.stroke(Color.blue, lineWidth: 10)
.frame(width: 300, height: 300)
}
}
struct CircleWaveView_Previews: PreviewProvider {
static var previews: some View {
CircleWaveView()
}
}
I want to mostly implement it on SwiftUI so that I can support dark mode! Thanks for the help!
Here's a complete standalone example. It features a slider which allows you to change the percentage:
import SwiftUI
struct ContentView: View {
@State private var percent = 50.0
var body: some View {
VStack {
CircleWaveView(percent: Int(self.percent))
Slider(value: self.$percent, in: 0...100)
}
.padding(.all)
}
}
struct Wave: Shape {
var offset: Angle
var percent: Double
var animatableData: Double {
get { offset.degrees }
set { offset = Angle(degrees: newValue) }
}
func path(in rect: CGRect) -> Path {
var p = Path()
// empirically determined values for wave to be seen
// at 0 and 100 percent
let lowfudge = 0.02
let highfudge = 0.98
let newpercent = lowfudge + (highfudge - lowfudge) * percent
let waveHeight = 0.015 * rect.height
let yoffset = CGFloat(1 - newpercent) * (rect.height - 4 * waveHeight) + 2 * waveHeight
let startAngle = offset
let endAngle = offset + Angle(degrees: 360)
p.move(to: CGPoint(x: 0, y: yoffset + waveHeight * CGFloat(sin(offset.radians))))
for angle in stride(from: startAngle.degrees, through: endAngle.degrees, by: 5) {
let x = CGFloat((angle - startAngle.degrees) / 360) * rect.width
p.addLine(to: CGPoint(x: x, y: yoffset + waveHeight * CGFloat(sin(Angle(degrees: angle).radians))))
}
p.addLine(to: CGPoint(x: rect.width, y: rect.height))
p.addLine(to: CGPoint(x: 0, y: rect.height))
p.closeSubpath()
return p
}
}
struct CircleWaveView: View {
@State private var waveOffset = Angle(degrees: 0)
let percent: Int
var body: some View {
GeometryReader { geo in
ZStack {
Text("\(self.percent)%")
.foregroundColor(.black)
.font(Font.system(size: 0.25 * min(geo.size.width, geo.size.height) ))
Circle()
.stroke(Color.blue, lineWidth: 0.025 * min(geo.size.width, geo.size.height))
.overlay(
Wave(offset: Angle(degrees: self.waveOffset.degrees), percent: Double(percent)/100)
.fill(Color(red: 0, green: 0.5, blue: 0.75, opacity: 0.5))
.clipShape(Circle().scale(0.92))
)
}
}
.aspectRatio(1, contentMode: .fit)
.onAppear {
withAnimation(Animation.linear(duration: 2).repeatForever(autoreverses: false)) {
self.waveOffset = Angle(degrees: 360)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
CircleWaveView(percent: 58)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With