Skip to content

Instantly share code, notes, and snippets.

@mike011
Created January 10, 2026 16:20
Show Gist options
  • Select an option

  • Save mike011/8409ecb331855cfb619430c0652b9bbe to your computer and use it in GitHub Desktop.

Select an option

Save mike011/8409ecb331855cfb619430c0652b9bbe to your computer and use it in GitHub Desktop.
//
// SparkleView.swift
// UnwrapLive26
//
// Created by Michael Charland on 2026-01-10.
//
import SwiftUI
struct Sparkle {
var x: Double
var y: Double
var xSpeed: Double
var ySpeed: Double
var size: Double
var brightness: Double
var creationDate = Date()
}
struct SparkleView: View {
@State private var sparkles = [Sparkle]()
var colours: [Color] = [.red, .green, .blue, .yellow, .pink, .purple, .orange]
var body: some View {
TimelineView(.animation) { timeline in
Canvas { context, size in
context.blendMode = .plusLighter
context.addFilter(.blur(radius: 10))
for sparkle in sparkles {
let age = timeline.date.timeIntervalSince(sparkle.creationDate)
context.opacity = (1 - age) * sparkle.brightness
// Move the sparkle based on its speed and age
let x = sparkle.x + sparkle.xSpeed * age
let y = sparkle.y + sparkle.ySpeed * age
let rectangle = CGRect(
x: x - sparkle.size / 2,
y: y - sparkle.size / 2,
width: sparkle.size,
height: sparkle.size
)
context.fill(Path(ellipseIn: rectangle), with: .color(colours.randomElement()!))
}
}
.gesture(
DragGesture(minimumDistance: 0)
.onChanged { value in
sparkles.append(
Sparkle(
x: value.location.x,
y: value.location.y,
xSpeed: Double.random(in: -50...50),
ySpeed: Double.random(in: -50...50),
size: Double.random(in: 16...32),
brightness: Double.random(in: 0.7...1)
)
)
// free up RAM
sparkles = sparkles.suffix(200)
}
)
}
}
}
#Preview {
SparkleView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment