如何重新启动正在进行的 CALayer 动画?

How do I restart a CALayer animation going on?

Apple 提到了这两种用于暂停和恢复正在进行的 CALayer 动画的方法

-(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;
}

但是如何重新启动动画?

这个其他问题与我需要的无关。

我在 ViewController 中采用了 blog 中的代码。看看方法 [resetEmitterLayer:]。在你的情况下,你需要做的重置动画如下:

  1. 从超级层移除发射层。
  2. 重新创建发射器层。
  3. 向层树添加新的发射器层。

请参阅下面的 ViewController 实现

#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