Skip to content

Instantly share code, notes, and snippets.

@cjhodge
Created November 15, 2025 14:36
Show Gist options
  • Select an option

  • Save cjhodge/5f4a0cdea365a54e55c0bfbdd3fdd501 to your computer and use it in GitHub Desktop.

Select an option

Save cjhodge/5f4a0cdea365a54e55c0bfbdd3fdd501 to your computer and use it in GitHub Desktop.
//
// SpeedLinesView.swift
//
//
// Created by Chris Hodge on 10/14/25.
//
import SwiftUI
struct SpeedLinesView: View {
@State private var staticLineRefresh = 0
var body: some View {
GeometryReader { geometry in
ZStack {
// Blue background
Color.blue
.ignoresSafeArea()
// Static long teardrop lines - refresh based on state
ForEach(0..<40, id: \.self) { index in
StaticSpeedLine(
angle: Double(index) * 9.0 + Double.random(in: -3...3),
opacity: Double.random(in: 0.2...0.6),
width: CGFloat.random(in: 15...50),
length: CGFloat.random(in: 600...1500),
startDistance: CGFloat.random(in: 60...150),
isBlue: Double.random(in: 0...1) < 0.3,
screenWidth: geometry.size.width,
screenHeight: geometry.size.height,
refreshId: staticLineRefresh
)
}
}
.onAppear {
Timer.scheduledTimer(withTimeInterval: 0.05, repeats: true) { _ in
staticLineRefresh += 1
}
}
}
}
}
struct StaticSpeedLine: View {
let angle: Double
let opacity: Double
let width: CGFloat
let length: CGFloat
let startDistance: CGFloat
let isBlue: Bool
let screenWidth: CGFloat
let screenHeight: CGFloat
let refreshId: Int
var body: some View {
let centerX = screenWidth / 2
let centerY = screenHeight / 2
let radians = angle * .pi / 180
let lineColor = isBlue ? Color(red: 0.7, green: 0.85, blue: 1.0) : Color.white
// Create long teardrop shape
Path { path in
let height = width
// Start at the narrow end (left)
path.move(to: CGPoint(x: 0, y: height / 2))
// Curve up to the wide end
path.addQuadCurve(
to: CGPoint(x: length, y: 0),
control: CGPoint(x: length * 0.6, y: 0)
)
// Curve across the wide end
path.addQuadCurve(
to: CGPoint(x: length, y: height),
control: CGPoint(x: length * 1.05, y: height / 2)
)
// Curve back down to the narrow end
path.addQuadCurve(
to: CGPoint(x: 0, y: height / 2),
control: CGPoint(x: length * 0.6, y: height)
)
}
.fill(
LinearGradient(
gradient: Gradient(colors: [
lineColor.opacity(0),
lineColor.opacity(opacity * 0.6),
lineColor.opacity(opacity),
lineColor.opacity(0)
]),
startPoint: .leading,
endPoint: .trailing
)
)
.frame(width: length, height: width)
.rotationEffect(.degrees(angle))
.offset(x: cos(radians) * (startDistance + length / 2), y: sin(radians) * (startDistance + length / 2))
.position(x: centerX, y: centerY)
}
}
#Preview {
SpeedLinesView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment