Search code examples
iosmacoscocoacocoa-touchcalayer

How do I restart a CALayer animation going on?


Apple mentions these two methods for pausing and resuming a CALayer animation going on

-(void)pauseLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
   layer.speed = 0.0;
   layer.timeOffset = pausedTime;
}

-(void)resumeLayer:(CALayer*)layer {
   CFTimeInterval pausedTime = [layer timeOffset];
   layer.speed = 1.0;
   layer.timeOffset = 0.0;
   layer.beginTime = 0.0;
   CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
   layer.beginTime = timeSincePause;
}

but how do I restart the animation?

this other SO question has nothing to do with what I need.


Solution

  • I have adopted code from blog in ViewController. Take a look at method [resetEmitterLayer:]. In your case all you need to do to reset animation is as follow:

    1. Remove emitter layer from super layer.
    2. Recreate emitter layer.
    3. Add new emitter layer to the layer tree.

    See ViewController implementation below

    #import "EmitterViewController.h"
    #import <QuartzCore/QuartzCore.h>
    
    @interface EmitterViewController ()
    
    @property (nonatomic, strong) CAEmitterLayer *emitterLayer;
    
    @end
    
    @implementation EmitterViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
    
        self.emitterLayer = [self createEmitterLayer];
    
        [self.view.layer addSublayer:self.emitterLayer];
    }
    
    -(CAEmitterLayer *)createEmitterLayer {
    
        CAEmitterLayer *emitterLayer = [CAEmitterLayer layer];
        emitterLayer.emitterPosition = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.origin.y);
        emitterLayer.emitterZPosition = 10;
        emitterLayer.emitterSize = CGSizeMake(self.view.bounds.size.width, 0);
        emitterLayer.emitterShape = kCAEmitterLayerSphere;
    
    
        CAEmitterCell *emitterCell = [CAEmitterCell emitterCell];
        emitterCell.scale = 0.1;
        emitterCell.scaleRange = 0.2;
        emitterCell.emissionRange = (CGFloat)M_PI_2;
        emitterCell.lifetime = 5.0;
        emitterCell.birthRate = 10;
        emitterCell.velocity = 200;
        emitterCell.velocityRange = 50;
        emitterCell.yAcceleration = 250;
    
        emitterCell.contents = (id)[[UIImage imageNamed:@"WaterDrop.png"] CGImage];
    
        emitterLayer.emitterCells = [NSArray arrayWithObject:emitterCell];
    
        return emitterLayer;
    }
    
    
    -(IBAction)pauseEmitterLayer:(id)sender
    {
        CFTimeInterval pausedTime = [self.emitterLayer convertTime:CACurrentMediaTime() fromLayer:nil];
        self.emitterLayer.speed = 0.0;
        self.emitterLayer.timeOffset = pausedTime;
    }
    
    -(IBAction)resumeEmitterLayer:(id)sender
    {
        CFTimeInterval pausedTime = [self.emitterLayer timeOffset];
        self.emitterLayer.speed = 1.0;
        self.emitterLayer.timeOffset = 0.0;
        self.emitterLayer.beginTime = 0.0;
        CFTimeInterval timeSincePause = [self.emitterLayer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
        self.emitterLayer.beginTime = timeSincePause;
    }
    
    -(IBAction)resetEmitterLayer:(id)sender
    {
        [self.emitterLayer removeFromSuperlayer];
    
        self.emitterLayer = [self createEmitterLayer];
    
        [self.view.layer addSublayer:self.emitterLayer];
    }
    
    @end