CAEmitterLayer испускает случайные нежелательные частицы на сенсорных событиях
Я пытаюсь настроить CAEmitterLayer
чтобы сделать эффект конфетти, и я столкнулся с двумя проблемами:
- Всякий раз, когда я устанавливаю
birthRate
в моих клетках к чему-то ненулевому, чтобы начать анимацию, я получаю поток ячеек, размещенных случайным образом на экране, которые обычно анимируются, и затем излучатель продолжает излучать должным образом после этого. - Всякий раз, когда
emitterCells
рисуют вещи на экране, каждый раз, когда я касаюсь экрана, излучатель рисуетemitterCells
в (казалось бы) случайных местах, которые существуют (казалось бы) случайное количество времени. Ничто в эмиттере не связано с какими-либо сенсорными событиями (т.е. я не намеренно рисую что-либо на сенсорном событии), но слой находится в виде, который имеет несколько встроенных видов. Чем больше я прикасаюсь, тем больше ячеек появляется.
Вот мой код для настройки эмиттера, а затем его запуска и остановки (после того, как я вызвал функцию остановки, касания на экране перестают создавать новые случайные элементы):
- (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];
}
Чтобы начать конфетти:
- (void)startConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:10.0] forKeyPath:@"emitterCells.confetti.birthRate"];
}
И чтобы остановить это:
- (void)stopConfettiAnimation
{
[self.confettiLayer setValue:[NSNumber numberWithInt:0.0] forKeyPath:@"emitterCells.confetti.birthRate"];
}
Опять же, как только он запускается, после начального потока случайных элементов, это работает просто отлично: все анимируется нормально, а когда birthRate позже устанавливается в ноль, оно завершается изящно. Кажется, что он реагирует на сенсорные события, и я понятия не имею, почему. Я попытался добавить emitterLayer в другое представление, отключить взаимодействие с пользователем в этом представлении, а затем добавить его в качестве подпредставления основного представления, но это не помогло.
Любая помощь / понимание будет высоко ценится!
Спасибо Сэм
3 ответа
Я знаю, что это старый пост, но у меня тоже была эта проблема. Jackslash хорошо отвечает на это в этом посте: iOS 7 CAEmitterLayer порождает частицы неуместно
Вам нужно установить beginTime на слое эмиттера, чтобы он начинался в текущее время с CACurrentMediaTime(). Кажется, проблема у нас возникает, потому что излучатель запущен уже в прошлом.
emitter.beginTime = CACurrentMediaTime();
Может быть, вы не проверяете, излучает ли частица, как в примере с Wenderlich, опубликованном Артуром Озиеранским? Я не вижу удвоения, пока чек на месте.
- (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"];
}
.h файл
#import <UIKit/UIKit.h>
@interface DWFParticleView : UIView
-(void)setEmitterPositionFromTouch: (CGPoint*)t;
-(void)setIsEmitting:(BOOL)isEmitting;
@end
.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
Я использовал этот код для создания собственного вида и для испускания частиц при касании
Вот оператор вызова для излучения частицы на ощупь
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint p = [[touches anyObject] locationInView:self.view];
[fireView setEmitterPositionFromTouch: &p];
[fireView setIsEmitting:YES];
}
может быть, это будет работать для вас.