Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save AppArtistry/4d43048ed248db396ad3ada4bad0ea99 to your computer and use it in GitHub Desktop.
Save AppArtistry/4d43048ed248db396ad3ada4bad0ea99 to your computer and use it in GitHub Desktop.
Flowing Particle Background
import SwiftUI
struct Particle: Hashable, Equatable {
var x: Double
var y: Double
var dateTimeToHide: Date
var fallSpeed: Double
}
class Particles: ObservableObject {
var particleSet = Set<Particle>()
func configure(using timelineDate: Date) {
particleSet = particleSet.filter { $0.dateTimeToHide >= timelineDate }
let particle = Particle(
x: Double.random(in: 0...1),
y: Double.random(in: 0...1),
dateTimeToHide: timelineDate + Double.random(in: 1...5),
fallSpeed: Double.random(in: 0...1)
)
particleSet.insert(particle)
}
}
struct FlowingParticlesView: View {
@StateObject private var particles = Particles()
var body: some View {
ZStack {
TimelineView(.animation) { timeline in
Canvas { context, canvasSize in
particles.configure(using: timeline.date)
for particle in particles.particleSet {
let timeDif = timeline.date.distance(to: particle.dateTimeToHide)
let rect = CGRect(
x: particle.x * canvasSize.width - (canvasSize.width * particle.x * timeDif),
y: particle.y * canvasSize.height - (canvasSize.height * particle.y * timeDif * particle.fallSpeed),
width: 5,
height: 5)
let shape = Circle().path(in: rect)
let color: Color = [Color.white, Color.purple.opacity(0.8)].randomElement() ?? .white
context.fill(shape, with: .color(color))
}
}
}
.background(.black)
VStack {
Spacer()
Text("You have\ncompleted\nfirst part of\nthe series!")
.font(.system(size: 40, weight: .ultraLight))
.multilineTextAlignment(.leading)
.padding(40)
.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.purple, lineWidth: 2)
)
Spacer()
Text("Keep Watching")
.padding()
.background(LinearGradient(colors: [.purple, .pink], startPoint: UnitPoint(x: 0, y: 0), endPoint: UnitPoint(x: 1, y: 1)))
.cornerRadius(40)
.foregroundColor(.white)
.padding(10)
.overlay(
RoundedRectangle(cornerRadius: 40)
.stroke(Color.purple, lineWidth: 2)
)
.onTapGesture {
print("Button tapped!")
}
}
.padding(40)
}
.ignoresSafeArea()
}
}
struct FlowingParticlesView_Previews: PreviewProvider {
static var previews: some View {
FlowingParticlesView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment