Skip to content

Instantly share code, notes, and snippets.

@MortenGregersen
Last active May 16, 2023 19:52
Show Gist options
  • Save MortenGregersen/51e24d0ff9cc052ffd76913f18662c77 to your computer and use it in GitHub Desktop.
Save MortenGregersen/51e24d0ff9cc052ffd76913f18662c77 to your computer and use it in GitHub Desktop.
An animating waveform view made with SwiftUI as seen here: https://mastodon.social/@mortengregersen/110377187270004199
//
// WaveformView.swift
// HeyAIku
//
// Created by Morten Bjerg Gregersen on 16/05/2023.
//
import SwiftUI
struct WaveformView: View {
@State private var waveformLines: [WaveformLine] = []
private let timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
var body: some View {
HStack(spacing: 3) {
ForEach(waveformLines) { $0 }
}
.onReceive(timer, perform: { _ in
regenerateWaveform()
})
.onAppear {
regenerateWaveform()
}
}
private func regenerateWaveform() {
let minHeight: CGFloat = 10
let maxHeight: CGFloat = 30
let delta: CGFloat = 10
withAnimation(Animation.easeInOut) {
var previousLine: WaveformLine?
waveformLines = (0..<5).map {
let lowerBound, upperBound: CGFloat
if waveformLines.isEmpty {
lowerBound = minHeight
upperBound = maxHeight
} else if let previousLine {
lowerBound = max(previousLine.height - delta, minHeight)
upperBound = min(previousLine.height + delta, maxHeight)
} else {
lowerBound = max(waveformLines[$0].height - delta, minHeight)
upperBound = min(waveformLines[$0].height + delta, maxHeight)
}
let currentLine = WaveformLine(id: $0, height: CGFloat.random(in: lowerBound..<upperBound))
previousLine = currentLine
return currentLine
}
}
}
struct WaveformLine: View, Identifiable {
let id: Int
let height: CGFloat
var body: some View {
RoundedRectangle(cornerRadius: 1)
.frame(width: 2, height: height)
}
}
}
struct WaveformView_Previews: PreviewProvider {
static var previews: some View {
WaveformView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment