Skip to content

Instantly share code, notes, and snippets.

@rudrankriyam
Created July 19, 2024 10:45
Show Gist options
  • Save rudrankriyam/1cc075a90edf542839c55fd48ecee013 to your computer and use it in GitHub Desktop.
Save rudrankriyam/1cc075a90edf542839c55fd48ecee013 to your computer and use it in GitHub Desktop.
MeshGradient on watchOS 11
import SwiftUI
import WatchConnectivity
struct CurrentSongView: View {
@EnvironmentObject var songInfoReceiver: SongInfoReceiver
@State var t: Float = 0.0
@State var timer: Timer?
var body: some View {
NavigationStack {
ZStack {
if #available(watchOS 11.0, *) {
MeshGradient(width: 3, height: 3, points: [
.init(0, 0), .init(0.5, 0), .init(1, 0),
[sinInRange(-0.8...(-0.2), offset: 0.439, timeScale: 0.342, t: t), sinInRange(0.3...0.7, offset: 3.42, timeScale: 0.984, t: t)],
[sinInRange(0.1...0.8, offset: 0.239, timeScale: 0.084, t: t), sinInRange(0.2...0.8, offset: 5.21, timeScale: 0.242, t: t)],
[sinInRange(1.0...1.5, offset: 0.939, timeScale: 0.084, t: t), sinInRange(0.4...0.8, offset: 0.25, timeScale: 0.642, t: t)],
[sinInRange(-0.8...0.0, offset: 1.439, timeScale: 0.442, t: t), sinInRange(1.4...1.9, offset: 3.42, timeScale: 0.984, t: t)],
[sinInRange(0.3...0.6, offset: 0.339, timeScale: 0.784, t: t), sinInRange(1.0...1.2, offset: 1.22, timeScale: 0.772, t: t)],
[sinInRange(1.0...1.5, offset: 0.939, timeScale: 0.056, t: t), sinInRange(1.3...1.7, offset: 0.47, timeScale: 0.342, t: t)]
], colors: songInfoReceiver.colors.map { Color(hex: $0) })
.onAppear {
timer = Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { _ in
t += 0.01
}
}
.background(Color.black)
.ignoresSafeArea()
} else {
// Fallback on earlier versions
}
if songInfoReceiver.hasSongInfo {
ScrollView {
VStack(alignment: .leading) {
Text(songInfoReceiver.artist)
.font(.subheadline)
.foregroundStyle(.secondary)
.padding(.bottom)
Text(songInfoReceiver.lyrics)
.font(.title3)
.bold()
}
.padding()
}
.navigationTitle(songInfoReceiver.title)
} else {
ContentUnavailableView(
"No Song Playing or Data Received",
systemImage: "music.note",
description: Text("Start playing a song on your iPhone to see the lyrics here.")
)
}
}
}
}
}
extension CurrentSongView {
private func sinInRange(_ range: ClosedRange<Float>, offset: Float, timeScale: Float, t: Float) -> Float {
let amplitude = (range.upperBound - range.lowerBound) / 2
let midPoint = (range.upperBound + range.lowerBound) / 2
return midPoint + amplitude * sin(timeScale * t + offset)
}
}
extension SongInfoReceiver {
var hasSongInfo: Bool {
!title.isEmpty || !artist.isEmpty || !lyrics.isEmpty
}
}
#Preview("With Song Info") {
CurrentSongView()
.environmentObject(SongInfoReceiver.mockWithSongInfo())
}
#Preview("Without Song Info") {
CurrentSongView()
.environmentObject(SongInfoReceiver.mockWithoutSongInfo())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment