SwiftUI curve waveform


hi I would like to achieve this kind of UI

enter image description here

however so far I only manage to make it looks like this

enter image description here

here is my full code where I have tried to achieve this

struct Wave: Shape {
    var animatableData: Double {
        get { phase }
        set { self.phase = newValue }
    }

    var strength: Double
    var frequency: Double
    var phase: Double
    var curveAmount: Double

    func path(in rect: CGRect) -> Path {
        var path = Path()

        let width = Double(rect.width)
        let height = Double(rect.height)
        let midWidth = width / 2
        let midHeight = height / 2

        let start = CGPoint(x: rect.minX, y: midHeight)
        let end = CGPoint(x: rect.maxX, y: midHeight)
        let control = CGPoint(x: midWidth, y: rect.minY + strength * curveAmount)

        path.move(to: start)

        for x in stride(from: 0, through: width, by: 1) {
            let progress = x / width
            let parabolicY = QuadBezier(t: progress, start: start.y, c: control.y, end: end.y)
            let sineWave = sin(progress * frequency * 2 * .pi + phase) * (strength * 0.5)
            let y = parabolicY + sineWave

            path.addLine(to: CGPoint(x: x, y: y))
        }

        return path
    }

    private func QuadBezier(t: Double, start: CGFloat, c: CGFloat, end: CGFloat) -> Double {
        let invT = 1 - t
        let b1 = 3 * t * (invT * invT)
        let b2 = 3 * (t * t) * invT
        let b3 = t * t * t

        let part1 = Double(start) * Double(invT * invT * invT)
        let part2 = Double(c) * Double(b1 + b2)
        let part3 = Double(end) * Double(b3)

        return part1 + part2 + part3
    }
}

struct ContentView: View {
    @State private var phase = 0.0

    var body: some View {
        ZStack {
            
            ForEach(0..<20) { i in
                Wave(strength: 10, frequency: 4, phase: self.phase, curveAmount: 30)
                    .stroke(Color.white.opacity(Double(i) / 10), lineWidth: 5)
                    .offset(y: CGFloat(i) * 1.2)
            }
            Wave(strength: 10, frequency: 0, phase: 0, curveAmount: 30)
                .stroke(Color.white, lineWidth: 5)
                .offset(y: 7 * 5)
        }
        .background(Color.blue)
        .edgesIgnoringSafeArea(.all)
        .onAppear {
            withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) {
                self.phase = .pi * 2
            }
        }
    }
}

does any one know how I can achieve this exact UI?

having hard time to achieve this

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img