2013-05-25 31 views
7

我想創建一個只在用戶觸摸屏幕時發出的粒子效果,但一旦設置爲非零值,我無法更改CAEmitterCell birthRate屬性。CAEmitterCell不尊重birthRate更改

我有一個UIView的子類,它設置我的CAEmitterLayer和我的CAEmitterCell只是我想要的方式。我對這個類定義兩個屬性:

@property (strong, nonatomic) CAEmitterLayer *emitterLayer; 
@property (strong, nonatomic) CAEmitterCell *emitterCell; 

然後,在我的視圖控制器,我跟蹤觸摸,設置emitterLayer的位置,並emitterCell出生率:

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    CGPoint tappedPt = [touch locationInView:touch.view]; 
    NSLog(@"began x:%f y:%f",tappedPt.x, tappedPt.y); 
    emitterView.emitterCell.birthRate = 42; 
    emitterView.emitterLayer.emitterPosition = tappedPt; 
} 

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch *touch = [touches anyObject]; 
    CGPoint tappedPt = [touch locationInView:touch.view]; 
    NSLog(@"moved x:%f y:%f",tappedPt.x, tappedPt.y); 
    emitterView.emitterLayer.emitterPosition = tappedPt; 
} 

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ 
    NSLog(@"ending %f", emitterView.emitterCell.birthRate); 
    emitterView.emitterCell.birthRate = 0.00; 
    NSLog(@"ended %f", emitterView.emitterCell.birthRate); 
} 

的日誌報告所述emitterView.emitterCell.birthRate改變:

began x:402.000000 y:398.500000 
ending 42.000000 
ended 0.000000 

當我觸摸屏幕時,如預期的發射器啓動時,層如下所述觸摸,但是當我結束觸摸時,EMIT ter單元愉快地發出最初設置的任何值(在touchesBegan中設置的值)。無論我做什麼,我似乎都無法改變一旦被設定爲非零值的出生率值。日誌報告值設置正確,但發射器不斷髮光。

但是,如果我改變touchesEnded方法來改變層的位置,之後我設置的出生率上emitterCell然後按預期工作的一切:

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{ 
    UITouch *touch = [touches anyObject]; 
    CGPoint tappedPt = [touch locationInView:touch.view]; 
    NSLog(@"began x:%f y:%f",tappedPt.x, tappedPt.y); 

    NSLog(@"ending %f", emitterView.emitterCell.birthRate); 
    emitterView.emitterCell.birthRate = 0.0; 
    NSLog(@"ended %f", emitterView.emitterCell.birthRate); 
    emitterView.emitterLayer.emitterPosition = tappedPt; 
} 

可有人請解釋一下爲什麼?

+0

你有沒有想出解決辦法? – scott

回答

6

我不知道爲什麼行爲是有點怪異,但我發現,使用鍵值編碼解決這個問題,並在細胞停止發射:

假設你CAEmitterLayer是「yourEmitterLayer」和你有一個名爲「yourEmitterCell」 CAEmitterCell,如果放在裏面touchesEnded這將停止發射:

[yourEmitterLayer setValue:[NSNumber numberWithInt:0] forKeyPath:@"emitterCells.yourEmitterCell.birthRate"]; 
+0

兩個問題:1)birthRate是float,你正在分配一個int。 2)發射器操作是否始終必須從其發射器開始?我的意思是,在這種情況下,您可以調用emitter並傳遞路徑'emitterCells.yourEmitterCell.birthRate',但假設我有對emitterCell本身的引用。我可以簡單地做'[self.emiterCell .... forKeyPath:@「birthRate」]'? – SpaceDog

+0

我還想知道上述評論者問題的答案 –

+0

要使用此代碼,您應該爲每個emittercell設置name屬性 self.yourEmitterCell.name = @「yourEmitterCell」, – Anees

2

要停止發光,你必須設置屬性實例的顆粒,雖然它最初設定CAEmitterCell實例...不知道爲什麼,但它的工作原理。

斯威夫特3例子:

func emitParticles() { 
    let particlesEmitter = CAEmitterLayer() 
    particlesEmitter.emitterPosition = center 
    particlesEmitter.emitterShape = kCAEmitterLayerCircle 
    particlesEmitter.emitterSize = CGSize(width: 50, height: 50) 
    particlesEmitter.renderMode = kCAEmitterLayerAdditive 

    let cell = CAEmitterCell() 
    cell.birthRate = 15 
    cell.lifetime = 1.0 
    cell.color = bubble.color.cgColor 
    cell.velocity = 150 
    cell.velocityRange = 50 
    cell.emissionRange = .pi 
    cell.scale = 0.1 
    cell.scaleSpeed = -0.1 

    cell.contents = UIImage(named: "particle")?.cgImage 
    particlesEmitter.emitterCells = [cell] 

    layer.addSublayer(particlesEmitter) 

    DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
     particlesEmitter.birthRate = 0 
    } 
}