'How can I make animation with CAEmitterLayer on SwiftUI?

How can I convert this code to SwiftUI. It's a snow effect. I used CAEmitterLayer but I don't know how to use it in SwfitUI. There is no addSublayer in SwiftUI. Is it possible to run this code without using UIHostingController ?

let size = CGSize(width: 824.0, height: 1112.0)
let host = UIView(frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
self.view.addSubview(host)

let particlesLayer = CAEmitterLayer()
particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)

host.layer.addSublayer(particlesLayer)
host.layer.masksToBounds = true

particlesLayer.backgroundColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
particlesLayer.emitterShape = .circle
particlesLayer.emitterPosition = CGPoint(x: 509.4, y: 707.7)
particlesLayer.emitterSize = CGSize(width: 1648.0, height: 1112.0)
particlesLayer.emitterMode = .surface
particlesLayer.renderMode = .oldestLast



                let image1 = UIImage(named: "logo")?.cgImage

                let cell1 = CAEmitterCell()
                cell1.contents = image1
                cell1.name = "Snow"
                cell1.birthRate = 92.0
                cell1.lifetime = 20.0
                cell1.velocity = 59.0
                cell1.velocityRange = -15.0
                cell1.xAcceleration = 5.0
                cell1.yAcceleration = 40.0
                cell1.emissionRange = 180.0 * (.pi / 180.0)
                cell1.spin = -28.6 * (.pi / 180.0)
                cell1.spinRange = 57.2 * (.pi / 180.0)
                cell1.scale = 0.06
                cell1.scaleRange = 0.3
                cell1.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor

                particlesLayer.emitterCells = [cell1]


Solution 1:[1]

Here is a solution. Tested with Xcode 11.4 / iOS 13.4

demo

struct EmitterView: UIViewRepresentable {
    func makeUIView(context: Context) -> UIView {
        let size = CGSize(width: 824.0, height: 1112.0)
        let host = UIView(frame: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))

        let particlesLayer = CAEmitterLayer()
        particlesLayer.frame = CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height)

        host.layer.addSublayer(particlesLayer)
        host.layer.masksToBounds = true

        particlesLayer.backgroundColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
        particlesLayer.emitterShape = .circle
        particlesLayer.emitterPosition = CGPoint(x: 509.4, y: 707.7)
        particlesLayer.emitterSize = CGSize(width: 1648.0, height: 1112.0)
        particlesLayer.emitterMode = .surface
        particlesLayer.renderMode = .oldestLast



        let image1 = UIImage(named: "logo")?.cgImage

        let cell1 = CAEmitterCell()
        cell1.contents = image1
        cell1.name = "Snow"
        cell1.birthRate = 92.0
        cell1.lifetime = 20.0
        cell1.velocity = 59.0
        cell1.velocityRange = -15.0
        cell1.xAcceleration = 5.0
        cell1.yAcceleration = 40.0
        cell1.emissionRange = 180.0 * (.pi / 180.0)
        cell1.spin = -28.6 * (.pi / 180.0)
        cell1.spinRange = 57.2 * (.pi / 180.0)
        cell1.scale = 0.06
        cell1.scaleRange = 0.3
        cell1.color = UIColor(red: 255.0/255.0, green: 255.0/255.0, blue: 255.0/255.0, alpha: 1.0).cgColor

        particlesLayer.emitterCells = [cell1]
        return host
    }

    func updateUIView(_ uiView: UIView, context: Context) {
    }

    typealias UIViewType = UIView
}

struct TestEmitterLayer: View {
    var body: some View {
        EmitterView()        // << usage !!
    }
}

backup

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1