JoePasq JoePasq - 27 days ago 8
iOS Question

CAEmitterLayer multiple cells interleaved

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
}




Answer Source

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 = "