CAEmitterLayer如何反复短时间发射

D33*_*D33 11 core-animation calayer uiview ios caemitterlayer

我正在玩CAEmitterLayer,我现在面临一些问题:(

我需要一个短的粒子效果 - 比如击中或爆炸 - 例如在一个地方(所以我在这个地方有小UIView).我该怎么办?

1,我有一个想法 - 使用它的粒子创建emitterLayer并将lifeTime设置为0.当我需要它时,我将lifeTime设置为1,一段时间后我可以将其设置为0. - 但是它没有做任何事情:(

2,第二个想法是每次需要时创建[CAEmitterLayer图层]并将其添加为图层子图层.但是我在想,当我重复十次时会发生什么......我有10个子层,一个有效,9个"死"?如何停止一般发射?我有一段时间后执行performSelector将生命周期设置为0,其他选择器的间隔时间更长,以删除.FromSuperlayer ...但它不是那么漂亮我想拥有它:(还有另一种"正确"方式吗?

我认为太多的子层与我的另一个问题有关...我想只发射一个粒子.当我这样做时,它有效.但有时候它发出三颗粒子,有时两粒......这让我很生气.当我不停止发射器时,它每次给出正确数量的粒子......

所以问题......

如何在短时间内发射粒子.如何使用它们 - 比如停止,从父层移除,...如何发出准确数量的粒子

编辑:

emitter = [CAEmitterLayer layer];
emitter.emitterPosition = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
emitter.emitterMode = kCAEmitterLayerPoints;
emitter.emitterShape    = kCAEmitterLayerPoint;
emitter.renderMode      = kCAEmitterLayerOldestFirst;
emitter.lifetime = 0;


particle = [CAEmitterCell emitterCell];
[particle setName:@"hit"];
particle.birthRate      = 1;
particle.emissionLongitude  = 3*M_PI_2;//270deg
particle.lifetime       = 0.75;
particle.lifetimeRange      = 0;
particle.velocity       = 110;
particle.velocityRange      = 20;
particle.emissionRange      = M_PI_2;//PI/2 = 90degrees
particle.yAcceleration      = 200;
particle.contents       = (id) [[UIImage imageNamed:@"50"] CGImage];
particle.scale          = 1.0;
particle.scaleSpeed     = -0.5;
particle.alphaSpeed     = -1.0;

emitter.emitterCells = [NSArray arrayWithObject:particle];
[(CAEmitterLayer *)self.view.layer addSublayer: emitter];
Run Code Online (Sandbox Code Playgroud)

然后在与按钮链接的方法中我这样做:

emitter.lifetime = 1.0;

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.9 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
    emitter.lifetime = 0;
});
Run Code Online (Sandbox Code Playgroud)

改为@DavidRönnqvist态度后编辑和更新

CAEmitterCell *dustCell = [CAEmitterCell emitterCell];
[dustCell setBirthRate:1];
[dustCell setLifetime:1.5];
[dustCell setName:@"dust"];
[dustCell setContents:(id) [[UIImage imageNamed:@"smoke"] CGImage]];
[dustCell setVelocity:50];
[dustCell setEmissionRange:M_PI];
// Various configurations for the appearance...
// This is the only cell with configured scale, 
// color, content, emissionLongitude, etc...

[emitter setEmitterCells:[NSArray arrayWithObject:dustCell]];
[(CAEmitterLayer *)self.view.layer addSublayer:emitter];

// After one burst, change the birth rate of the cloud to 0
// so that there is only one burst per side.
double delayInSeconds = 0.5; // One cloud will have been created by now, but not two
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {

    [emitter setLifetime:0.0];
    [emitter setValue:[NSNumber numberWithFloat:0.0] 
               forKeyPath:@"emitterCells.dust.birthRate"];
});
Run Code Online (Sandbox Code Playgroud)

Dav*_*ist 10

您可以通过配置一次(不要每次都添加新的发射器单元格)并将其设置birthRate为0(不会创建任何粒子)来完成此操作.然后,当您想要创建粒子时,可以将其设置为birthRate您想要创建的每秒粒子数.经过一段时间后,将其设置birthRate为0,以便停止发射.你可以使用像dispatch_after()这样的延迟.


我做了类似的事情,并像这样解决了.以下将创建一个快速爆发的粒子.下次想要粒子发射时,将"云"的birthRate更改回1.

CAEmitterCell *dustCell = [[CAEmitterCell alloc] init];
[dustCell setBirthRate:7000];
[dustCell setLifetime:3.5];
// Various configurations for the appearance...
// This is the only cell with configured scale, 
// color, content, emissionLongitude, etc...

CAEmitterCell *dustCloud = [CAEmitterCell emitterCell];
[dustCloud setBirthRate:1.0]; // Create one cloud every second
[dustCloud setLifetime:0.06]; // Emit dustCells for 0.06 seconds
[dustCloud setEmitterCells:[NSArray arrayWithObject:dustCell]];
[dustCloud setName:@"cloud"]; // Use this name to change the birthRate later

[dustEmitter setEmitterPosition:myPositionForDustEmitter];
[rightDustEmitter setEmitterCells:[NSArray arrayWithObject:dustCloud]];

// After one burst, change the birth rate of the cloud to 0
// so that there is only one burst per side.
double delayInSeconds = 0.5; // One cloud will have been created by now, but not two
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {

    // For some reason, setting the birthRate of the "cloud" to 0
    // has a strange side effect that when you set it back to 1 all
    // the missed emissions seems to happen at once during the first
    // emission and then it goes back to only emitting once per
    // second. (Thanks D33 for pointing this out).
    // By instead changing the birthRate of the "dust" particle
    // to 0 and then back to (in my case) 7000 gives the visual
    // effect that I'm expecting. I'm not sure why it works
    // this way but at least this works for me...
    // NOTE: This is only relevant in case you want to re-use
    // the emitters for a second emission later on by setting
    // the birthRate up to a non-zero value.
    [dustEmitter setValue:[NSNumber numberWithFloat:0.0] 
               forKeyPath:@"emitterCells.cloud.emitterCells.dust.birthRate"];
});
Run Code Online (Sandbox Code Playgroud)


tho*_*max 6

感谢foundrys 在这里的出色答案,我解决了一个与此非常相似的问题.它不涉及隐藏任何视图.简而言之,它是这样的:

像往常一样设置发射器,命名发射器单元并给它们一个出生值为零:

-(void) setUpEmission {
  # ...
  # snip lots of config
  # ...
  [emitterCell1 setBirthrate:0];
  [emitterCell1 setName:@"emitter1"];
  [emitterCell2 setBirthrate:0];
  [emitterCell2 setName:@"emitter2"];
  emitterLayer.emitterCells = @[emitterCell1, emitterCell2];
  [self.view.layer addSublayer:emitterLayer];
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个启动方法,在一段时间后自动关闭发射,并停止方法:

-(void) startEmission {
  [emitterLayer setValue:@600 forKeyPath:@"emitterCells.emitter1.birthRate"];
  [emitterLayer setValue:@250 forKeyPath:@"emitterCells.emitter2.birthRate"];
  [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(stopEmission) userInfo:nil repeats:NO];
}

-(void) stopEmission {
  [emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitter1.birthRate"];
  [emitterLayer setValue:@0 forKeyPath:@"emitterCells.emitter2.birthRate"];
}
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我将出生率设置为600和250.定时器在0.2秒后关闭发射,但使用你认为合适的任何东西.

如果Apple实施了启动/停止方法,那么最佳解决方案就是如此,但我认为这是一个令人满意的解决方案.


sha*_*oga 5

我也在寻找解决方案并找到了这篇文章.

看看这个Gist的五彩纸屑粒子及其Stop Emitting方法.

它的作用是:

  1. 将粒子视图添加到显示视图.
  2. 让粒子尽可能长时间运行.
  3. 停止发射新的颗粒confettiEmitter.birthRate = 0.0;.
  4. 等几秒钟.
  5. 删除粒子视图.

希望它可以提供帮助.