Created
July 21, 2023 09:20
-
-
Save deurell/a4fde0b9b476b4e6e2d3e0bacc8e8c46 to your computer and use it in GitHub Desktop.
SwiftUI confetti effect.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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