Skip to content

Instantly share code, notes, and snippets.

@deurell
Created July 21, 2023 09:20
Show Gist options
  • Save deurell/a4fde0b9b476b4e6e2d3e0bacc8e8c46 to your computer and use it in GitHub Desktop.
Save deurell/a4fde0b9b476b4e6e2d3e0bacc8e8c46 to your computer and use it in GitHub Desktop.
SwiftUI confetti effect.
//
// ConfettiView.swift
// Glosify
//
// Created by Mikael Deurell on 2023-07-21.
//
import Foundation
import SwiftUI
struct ConfettiView: View {
var body: some View {
GeometryReader { geometry in
ConfettiUIViewRepresentable(rect: geometry.frame(in: .local))
}
}
}
struct ConfettiUIViewRepresentable: UIViewRepresentable {
let rect: CGRect
func makeUIView(context: Context) -> ConfettiUIView {
let view = ConfettiUIView(frame: .zero)
view.isUserInteractionEnabled = false
return view
}
func updateUIView(_ uiView: ConfettiUIView, context: Context) {
uiView.frame = rect
}
}
class ConfettiUIView: UIView {
private var particleEmitter: CAEmitterLayer?
override func layoutSubviews() {
super.layoutSubviews()
if particleEmitter == nil {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in
self?.setupEmitter()
}
}
}
private func setupEmitter() {
let particleEmitter = CAEmitterLayer()
particleEmitter.emitterPosition = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 4.0)
particleEmitter.emitterShape = .point
particleEmitter.emitterCells = generateEmitterCells()
layer.addSublayer(particleEmitter)
self.particleEmitter = particleEmitter
// After the explosion, stop emitting particles.
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
particleEmitter.birthRate = 0
}
}
private func generateEmitterCells() -> [CAEmitterCell] {
var cells:[CAEmitterCell] = [CAEmitterCell]()
for _ in 0..<6 {
let cell = CAEmitterCell()
cell.birthRate = 16.0
cell.lifetime = 16.0
cell.velocity = CGFloat(350.0)
cell.velocityRange = CGFloat(100.0)
cell.emissionLongitude = CGFloat(0)
cell.emissionRange = CGFloat(2 * Double.pi)
cell.spin = 3.5
cell.spinRange = 1.0
cell.yAcceleration = 256
cell.scale = 1.0
cell.scaleRange = 0.1
cell.color = randomColor().cgColor
cell.contents = UIImage(named: "confetti")?.cgImage
cells.append(cell)
}
return cells
}
private func randomColor() -> UIColor {
let colors: [UIColor] = [.red, .blue, .green, .yellow]
return colors[Int.random(in: 0..<colors.count)]
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment