objective c - CAEmitterLayer emite partículas no deseadas aleatorias en eventos táctiles
objective-c ios (3)
archivo .h
#import <UIKit/UIKit.h>
@interface DWFParticleView : UIView
-(void)setEmitterPositionFromTouch: (CGPoint*)t;
-(void)setIsEmitting:(BOOL)isEmitting;
@end
archivo .m
#import "DWFParticleView.h"
#import <QuartzCore/QuartzCore.h>
@implementation DWFParticleView
{
CAEmitterLayer* fireEmitter; //1
}
-(void)awakeFromNib
{
//set ref to the layer
fireEmitter = (CAEmitterLayer*)self.layer; //2
//configure the emitter layer
fireEmitter.emitterPosition = CGPointMake(50, 50);
fireEmitter.emitterSize = CGSizeMake(10, 10);
CAEmitterCell* fire = [CAEmitterCell emitterCell];
fire.birthRate = 0;
fire.lifetime = 1.5;
fire.lifetimeRange = 0.3;
fire.color = [[UIColor colorWithRed:255 green:255 blue:255 alpha:0.1] CGColor];
fire.contents = (id)[[UIImage imageNamed:@"Particles_fire.png"] CGImage];
[fire setName:@"fire"];
fire.velocity =5;
fire.velocityRange = 20;
fire.emissionRange = M_PI_2;
fire.scaleSpeed = 0.1;
fire.spin = 0.5;
fireEmitter.renderMode = kCAEmitterLayerAdditive;
//add the cell to the layer and we''re done
fireEmitter.emitterCells = [NSArray arrayWithObject:fire];
}
+ (Class) layerClass //3
{
//configure the UIView to have emitter layer
return [CAEmitterLayer class];
}
-(void)setEmitterPositionFromTouch: (CGPoint*)t
{
//change the emitter''s position
fireEmitter.emitterPosition = (*t);
}
-(void)setIsEmitting:(BOOL)isEmitting
{
//turn on/off the emitting of particles
[fireEmitter setValue:[NSNumber numberWithInt:isEmitting?100:0] forKeyPath:@"emitterCells.fire.birthRate"];
}
@end
Utilicé este código para crear una vista personalizada y para emitir partículas al tacto
Aquí está la declaración de llamada para la emisión de partículas en contacto
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.view];
[fireView setEmitterPositionFromTouch: &p];
[fireView setIsEmitting:YES];
}
Puede ser que funcione para usted.
Estoy tratando de configurar un CAEmitterLayer
para hacer un efecto de confeti, y me he encontrado con dos problemas:
- Cada vez que configuro la
birthRate
debirthRate
en mis celdas con un valor distinto de cero para iniciar la animación, obtengo una serie de celdas colocadas al azar en la pantalla, que se animan normalmente, y luego el emisor continúa emitiendo correctamente después de eso. - Cada vez que las
emitterCells
dibujan cosas en la pantalla, cada vez que toco la pantalla, el emisor dibujaemitterCells
enemitterCells
(aparentemente) aleatorias que existen durante un tiempo (aparentemente) aleatorio. Nada en el emisor está vinculado a ningún evento táctil (es decir, no estoy dibujando nada en un evento táctil), pero la capa está en una vista que tiene múltiples vistas incrustadas. Cuanto más toco, más células aparecen.
Aquí está mi código para configurar el emisor, y luego iniciarlo y detenerlo (una vez que haya llamado a la función de parada, luego toque en la pantalla y deje de crear nuevos elementos aleatorios):
- (void)setupConfetti
{
self.confettiLayer = [CAEmitterLayer layer];
[self.view.layer addSublayer:self.confettiLayer];
[self.view.layer setNeedsDisplay];
self.confettiLayer.emitterPosition = CGPointMake(1024.0/2,-50.0);
self.confettiLayer.emitterSize = CGSizeMake(1000.0, 10.0);
self.confettiLayer.emitterShape = kCAEmitterLayerLine;
self.confettiLayer.renderMode =kCAEmitterLayerUnordered;
CAEmitterCell *confetti = [CAEmitterCell emitterCell];
confetti1.contents = (id)[[UIImage imageNamed:@"confetti.png"] CGImage];
confetti.emissionLongitude = M_PI;
confetti.emissionLatitude = 0;
confetti.lifetime = 5;
confetti.birthRate = 0.0;
confetti.velocity = 125;
confetti.velocityRange = 50;
confetti.yAcceleration = 50;
confetti.spin = 0.0;
confetti.spinRange = 10;
confetti.name = @"confetti1";
self.confettiLayer.emitterCells = [NSArray arrayWithObjects:confetti, nil];
}
Para iniciar el confeti:
- (void)startConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:10.0] forKeyPath:@"emitterCells.confetti.birthRate"];
}
Y para detenerlo:
- (void)stopConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:0.0] forKeyPath:@"emitterCells.confetti.birthRate"];
}
Nuevamente, una vez que comienza, después de la ráfaga inicial de elementos aleatorios, esto funciona bien: todo se anima normalmente, y cuando la tasa de natalidad se establece en cero, termina con gracia. Simplemente parece responder a eventos táctiles, y no tengo idea de por qué. He intentado agregar el emitterLayer a una vista diferente, deshabilitar la interacción del usuario en esa vista y luego agregarla como una subvista de la vista principal, y parece que no funcionó.
Cualquier ayuda / conocimiento sería muy apreciado!
Gracias sam
¿Podría ser que no esté verificando si la partícula está emitiendo, como en el ejemplo de Wenderlich que publicó Artur Ozieranski? No veo la duplicación mientras el cheque esté en su lugar.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setEmitterPositionFromTouch: [touches anyObject]];
[fireView setIsEmitting:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setIsEmitting:NO];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[fireView setIsEmitting:NO];
}
-(void)setIsEmitting:(BOOL)isEmitting
{
//turn on/off the emitting of particles
[fireEmitter setValue:[NSNumber numberWithInt:isEmitting?200:0] forKeyPath:@"emitterCells.fire.birthRate"];
}
Sé que este es un post antiguo, pero también tuve este problema. Jackslash responde bien en esta publicación: iOS 7 CAEmitterLayer genera partículas de manera inapropiada
Debe establecer beginTime en su capa de emisor para comenzar en el momento actual con CACurrentMediaTime (). Parece que el problema que tenemos se produce porque el emisor ya comenzó en el pasado.
emitter.beginTime = CACurrentMediaTime();