0

I have a CAEmitterLayer instance that emits some CAEmitterCells. I'm wondering, is it possible to pause this layer such that no new CAEmitterCells are produced and the ones that have been produced remained fixed in their position on the screen? Then, when the CAEmitterLayer instance is "un-paused", the fixed CAEmitterCells on the screen start to move again.

Thanks for any help here.

EDIT

Setting:

emitterLayer.speed = 0.1

where emitterLayer is an instance of a subclass of CAEmitterLayer, just removes the layer completely from the view.

Setting:

emitterLayer.lifetime = 0.0

just stops any new emitterCells being produced but doesn't "freeze" the existing emitterCells at the current position.

ajrlewis
  • 2,968
  • 3
  • 33
  • 67

1 Answers1

2

You can set the lifetime property of the CAEmitterLayer to 0, which will cause newly emitted cells to not even be rendered, but will leave already existing cells unaffected. When you want to "un-pause" your emitter layer, you can simply reset lifetime to whatever it was before the pause.

To freeze the existing cells as well, you can set speed to 0 and also add a timeOffset.

extension CAEmitterLayer {
    func pause() {
        // Freeze existing cells
        self.speed = 0
        self.timeOffset = convertTime(CACurrentMediaTime(), from: self)
        // Stop creating new cells
        self.lifetime = 0
    }
}

Then you can simply call it like emitterLayer.pause()

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
  • Thanks for the suggestion. `emitterLayer.lifetime = 0` does stop **new** `emitterCells` from being made, but doesn't *freeze* the position of `emitterCells` that are already on the screen ... – ajrlewis Oct 03 '18 at 09:13
  • @AlexJ.R.Lewis you're right, check my updated answer, this should take care of existing cells as well – Dávid Pásztor Oct 03 '18 at 09:24
  • Thanks for the update. Unfortunately I can't quite get this to work. Setting `speed` to anything <1 makes the cells jump vertically upwards. Setting `timeOffset` to >0 makes cells move downwards, which counteracts this I guess? However `convertTime(CACurrentMediaTime(), from: self) = 173180.467530244 `, which is far too large? Thanks again. – ajrlewis Oct 03 '18 at 10:11
  • @AlexJ.R.Lewis did you actually try these exact values that are present in my answer? You shouldn't set `speed` to anything <1, but set it to exactly 0 and `timeOffset` should be exactly as in my answer following the documentation notes: _"/* Additional offset in active local time. i.e. to convert from parent * time tp to active local time t: t = (tp - begin) * speed + offset. * One use of this is to "pause" a layer by setting `speed' to zero and * `offset' to a suitable value. Defaults to 0. */"_ – Dávid Pásztor Oct 03 '18 at 10:16
  • Yes I tried your exact values, but they just removed the layer from the screen. I then adjusted the `speed` and `timeOffset` to understand what each of them was doing. I'm using Swift 4 targeted to iOS 11.4 by the way. – ajrlewis Oct 03 '18 at 10:19