user4806509
user4806509

Reputation: 3011

How To Change Contents Of A CAEmitterCell In A CAEmitterLayer Particle Emitter

Background

I have a function that creates a core animation emitter layer that animates myImage1, in the code below.

I want to change myImage1 to myImage2 to myImage3 and back to myImage1 after a delay of 10 seconds or every time a button is tapped.

I’ve tried unsuccessfully. The code myEmitterChange() is executed but the image doesn’t change in the core animation emitter layer. What needs to be corrected in the code below?


Questions

1 - How do I change the emitter layer image once the CAEmitterLayer is added to a view ?

2 - How do I completely stop the CAEmitterLayer animation and remove it entirely from the view?


Code

import UIKit

class ViewController: UIViewController {

var myEmitterLayer = CAEmitterLayer()
var myEmitterCell = CAEmitterCell()

override func viewDidLoad() {
    
    myEmitter()
    
    self.perform(#selector(self.myEmitterChange), with: nil, afterDelay: 10)

}

@objc func myEmitterChange() {
    
    print("Did I Change?")
    
    myEmitterCell.color = UIColor.orange.cgColor
    myEmitterCell.contents = UIImage(named: "myImage2")!.cgImage
    
}


func myEmitter() {
        
    myEmitterCell.birthRate = 1
    myEmitterCell.color = UIColor.blue.cgColor
    myEmitterCell.contents = UIImage(named: "myImage1")!.cgImage
    myEmitterCell.lifetime = 15
    myEmitterCell.scale = 0.25
    myEmitterCell.scaleSpeed = 0.025
    myEmitterCell.velocity = 50
    myEmitterCell.velocityRange = 50
    myEmitterCell.spin = -2

    myEmitterLayer.beginTime = CACurrentMediaTime()
    myEmitterLayer.birthRate = 1
    myEmitterLayer.emitterMode = CAEmitterLayerEmitterMode.outline
    myEmitterLayer.emitterPosition = CGPoint(x: (view.bounds.size.width * 0.5), y: (view.bounds.size.height * 0.5))
    myEmitterLayer.emitterShape = CAEmitterLayerEmitterShape.circle
    myEmitterLayer.emitterSize = CGSize(width: 10, height: 10)
    myEmitterLayer.renderMode = CAEmitterLayerRenderMode.oldestLast
    myEmitterLayer.emitterCells = [myEmitterCell]

    view.layer.addSublayer(myEmitterLayer)
    
    }

}

Upvotes: -1

Views: 322

Answers (1)

user4806509
user4806509

Reputation: 3011

Changing the image

1 - Add in the myEmitter() function a name property to myEmitterCell.

    myEmitterCell.name = "myEmitterCellName"

2 - Add in the myEmitterChange() function a setValue method to myEmitterLayer.

    myEmitterLayer.setValue(UIColor.orange.cgColor, forKeyPath: "emitterCells.myEmitterCellName.color")
    myEmitterLayer.setValue(UIImage(named: "myImage2")!.cgImage, forKeyPath: "emitterCells.myEmitterCellName.contents")

3 - Remove in the myEmitterChange() function the myEmitterCell.color and myEmitterCell.contents lines.

//    myEmitterCell.color = UIColor.orange.cgColor
//    myEmitterCell.contents = UIImage(named: "myImage2")!.cgImage

Stopping the animation

1 - Add in the myEmitterStop() function a setValue method to myEmitterLayer.

myEmitterLayer.setValue(0, forKeyPath: "emitterCells.myEmitterCellName.birthRate")

Code

import UIKit

class ViewController: UIViewController {

var myEmitterLayer = CAEmitterLayer()
var myEmitterCell = CAEmitterCell()

override func viewDidLoad() {
    
    myEmitter()
    
    self.perform(#selector(self.myEmitterChange), with: nil, afterDelay: 10)

    self.perform(#selector(self.myEmitterStop), with: nil, afterDelay: 20)  // <- Add this line

}


@objc func myEmitterStop() {

    print("Did I Stop?")

    myEmitterLayer.setValue(0, forKeyPath: "emitterCells.myEmitterCellName.birthRate")  // <- Add this line

}


@objc func myEmitterChange() {
    
    print("Did I Change?")
    
//    myEmitterCell.color = UIColor.orange.cgColor   // <- Remove this line
//    myEmitterCell.contents = UIImage(named: "myImage2")!.cgImage   // <- Remove this line
    
    myEmitterLayer.setValue(UIColor.orange.cgColor, forKeyPath: "emitterCells.myEmitterCellName.color")  // <- Add this line
    myEmitterLayer.setValue(UIImage(named: "myImage2")!.cgImage, forKeyPath: "emitterCells.myEmitterCellName.contents")  // <- Add this line
    
}


func myEmitter() {
    
    myEmitterCell.name = "myEmitterCellName" // <- Add this line
        
    myEmitterCell.birthRate = 1
    myEmitterCell.color = UIColor.blue.cgColor
    myEmitterCell.contents = UIImage(named: "myImage1")!.cgImage
    myEmitterCell.lifetime = 15
    myEmitterCell.scale = 0.25
    myEmitterCell.scaleSpeed = 0.025
    myEmitterCell.velocity = 50
    myEmitterCell.velocityRange = 50
    myEmitterCell.spin = -2

    myEmitterLayer.beginTime = CACurrentMediaTime()
    myEmitterLayer.birthRate = 1
    myEmitterLayer.emitterMode = CAEmitterLayerEmitterMode.outline
    myEmitterLayer.emitterPosition = CGPoint(x: (view.bounds.size.width * 0.5), y: (view.bounds.size.height * 0.5))
    myEmitterLayer.emitterShape = CAEmitterLayerEmitterShape.circle
    myEmitterLayer.emitterSize = CGSize(width: 10, height: 10)
    myEmitterLayer.renderMode = CAEmitterLayerRenderMode.oldestLast
    myEmitterLayer.emitterCells = [myEmitterCell]

    view.layer.addSublayer(myEmitterLayer)
    
    }

}

Upvotes: 2

Related Questions