Подтвердить что ты не робот

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 в другое представление, отключив взаимодействие пользователя с этим представлением, а затем добавив его в качестве подсмотра основного представления, и это, похоже, не работает.

Любая помощь/понимание будут оценены очень высоко!

Спасибо, Сэм

4b9b3361

Ответ 1

Я знаю, что это старый пост, но у меня также была эта проблема. Jackslash хорошо отвечает на этот пост: iOS 7 CAEmitterLayer непреднамеренно порождает частицы

Вам нужно установить beginTime на вашем уровне излучателя, чтобы начать с текущего времени с CACurrentMediaTime(). Похоже, проблема возникает, потому что эмиттер начал уже в прошлом.

emitter.beginTime = CACurrentMediaTime();

Ответ 2

Может быть, вы не проверяете, испускает ли частица, как в примере Вендерлиха, опубликованном Артуром Озъярским? Я не вижу удвоения, пока чек на месте.

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

Ответ 3

.h файл

 #import <UIKit/UIKit.h>

    @interface DWFParticleView : UIView

    -(void)setEmitterPositionFromTouch: (CGPoint*)t;
    -(void)setIsEmitting:(BOOL)isEmitting;

    @end

.m file

  #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 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];

}

может быть, это сработает для вас.