Reputation: 5234
I've mostly seen examples of continuous emitters in Swift, and I've found one example in Obj-C by setting the birthRates of the emitter cells to 0.0, but it doesn't seem to work, so I must be doing something wrong. In my example, I can see the message that the birth rate was set to 0 sixteen times, but the particles continue to flow endlessly.
@IBAction func particleBtnAction(_ sender: Any) {
let emitter = CAEmitterLayer()
emitter.emitterPosition = CGPoint(x: self.view.frame.size.width / 2, y: -10)
emitter.emitterShape = kCAEmitterLayerLine
emitter.emitterSize = CGSize(width: self.view.frame.size.width, height: 2.0)
emitter.emitterCells = generateEmitterCells()
self.view.layer.addSublayer(emitter)
// perform selector after 1.5 seconds when particles start
perform(#selector(endParticles), with: emitter, afterDelay: 1.5)
}
private func generateEmitterCells() -> [CAEmitterCell] {
var cells:[CAEmitterCell] = [CAEmitterCell]()
for index in 0..<16 {
let cell = CAEmitterCell()
cell.birthRate = 4.0
cell.lifetime = 1.0
cell.lifetimeRange = 0
cell.velocity = 0.7
cell.velocityRange = 0
cell.emissionLongitude = CGFloat(Double.pi)
cell.emissionRange = 0.5
cell.spin = 3.5
cell.spinRange = 0
cell.scaleRange = 0.25
cell.scale = 0.1
cells.append(cell)
}
return cells
}
@objc func endParticles(emitterLayer:CAEmitterLayer) {
for emitterCell in emitterLayer.emitterCells! {
emitterCell.birthRate = 0.0
print("birth rate set to 0")
}
}
Upvotes: 6
Views: 2273
Reputation: 393
What worked for me is this:
let emmitter = CAEmitterLayer()
let cell = makeCell()
emmitter.emitterCells = [cell]
view.layer.addSublayer(emmitter)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
emmitter.removeFromSuperlayer()
}
Upvotes: 0
Reputation: 93
You might try setting the isHidden property when you want to endParticles
emitter.isHidden = true
But note that all the cells instantly vanish, no matter when they were emitted, or their lifetime.
Another possibility would be to set all the scale related properties to 0, and then the lifetime and birthrate would not matter, as newly emitted cells would not be visible.
cell.scaleSpeed = 0
cell.scaleRange = 0
cell.scale = 0
Upvotes: 0
Reputation: 3058
Setting the CAEmitterLayer
's lifetime
to zero stops any new emitterCells
being emitted:
@objc func endParticles(emitterLayer:CAEmitterLayer) {
emitterLayer.lifetime = 0.0
}
Upvotes: 12
Reputation: 5234
You can use key paths to assign a name to each cell and loop through them, changing each cell's property when you want to change them:
private func generateEmitterCells() -> [CAEmitterCell] {
var cells:[CAEmitterCell] = [CAEmitterCell]()
for index in 0..<16 {
let cell = CAEmitterCell()
cell.birthRate = 4.0
cell.lifetime = 1.0
cell.lifetimeRange = 0
cell.velocity = 0.7
cell.velocityRange = 0
cell.emissionLongitude = CGFloat(Double.pi)
cell.emissionRange = 0.5
cell.spin = 3.5
cell.spinRange = 0
cell.scaleRange = 0.25
cell.scale = 0.1
cell.name = "cell\(index)" // cell name
cells.append(cell)
}
return cells
}
@objc func endParticles(emitterLayer:CAEmitterLayer) {
for i in 0..<(emitterLayer.emitterCells?.count ?? 0){
emitterLayer.setValue(0.0, forKeyPath: "emitterCells.cell\(i).birthRate")
print("birth rate set to 0")
}
}
Upvotes: 0