I have a CAEmitterLayer
with an array of CAEmitterCell
s. I want each the output of all cells to be intermingled. Right now the first cell in the array always draws above the other cells.
I've adjusted the renderMode
of the layer and the zAcceleration
of each cell but neither has solved this problem.
Some sample code:
func layoutSubviews() {
// ...
emitterLayer.frame = self.bounds
emitterLayer.seed = UInt32(Date().timeIntervalSinceNow)
emitterLayer.renderMode = kCAEmitterLayerOldestFirst
emitterLayer.emitterPosition = CGPoint(x: bounds.midX, y: bounds.midY)
emitterLayer.emitterSize = CGSize.init(width: bounds.width, height: 0)
emitterLayer.emitterShape = kCAEmitterLayerLine
self.layer.addSublayer(emitterLayer)
}
private func animate() {
// ...
if emitterLayer.emitterCells == nil || emitterLayer.emitterCells?.count == 0 {
let cells = (1...8).map { i -> CAEmitterCell in
if let img = UIImage.init(named: "Slice-\(i)") {
return createEmitterCell(image: img, index: i)
} else {
fatalError()
}
}
emitterLayer.emitterCells = cells
}
}
private func createEmitterCell(image: UIImage, index: Int) -> CAEmitterCell {
let cell = CAEmitterCell.init()
cell.isEnabled = true
cell.contents = image.cgImage
cell.contentsRect = CGRect(origin: CGPoint.zero, size: CGSize(width: 1, height: 1))
cell.birthRate = Float(index)
cell.lifetime = 3
cell.velocity = 7
cell.velocityRange = 3
cell.scale = 0.5
cell.emissionRange = (95 * CGFloat.pi / 180.0)
cell.emissionLatitude = (27 * CGFloat.pi / 180.0)
cell.emissionLongitude = (139 * CGFloat.pi / 180.0)
cell.xAcceleration = 10.0
cell.yAcceleration = 100.0
cell.zAcceleration = 10 * CGFloat(index)
return cell
}
I have 12 emitter cells and my solution is to randomize the order of emitters. This way each run of the application produces a different ordering.
emojiCells = "😃💪🏆🎊🎉💯✨✅🔷🙌💫🏁"
.characters
.sorted(by: { (a, b) -> Bool in
return arc4random() % 2 == 0
}).enumerated().map({ (offset: Int, element: Character) -> CAEmitterCell in
// create emitter cells for each emoji
let raster = rasterize(emoji: element)
return createEmitterCell(image: raster, index: offset)
})
emitterLayer.emitterCells = emojiCells
If I had fewer emitter cells then I would include duplicate emitters around each other. Such as [cell1, cell2, cell1]
. Other adjustments would help in that situation such as increasing the birth rate of cell2
.