Анимация CAEmitterLayer emitterPosition

Я пытаюсь оживить CAEmitterLayer"s emitterPosition как это:

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"emitterPosition.x"] ;
animation.toValue = (id) toValue ;
animation.removedOnCompletion = NO ;
animation.duration = self.translationDuration ;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut] ;
animation.completion = ^(BOOL finished)
    {
    [self animateToOtherSide] ;
    } ;
[_emitterLayer addAnimation:animation forKey:@"emitterPosition"] ;
CGPoint newEmitterPosition = CGPointMake(toValue.floatValue, self.bounds.size.height/2.0) ;
_emitterLayer.emitterPosition = newEmitterPosition ;

Обратите внимание, что animation.completion объявлен в категории, которая просто вызывает соответствующий CAAnimation метод делегата.

Проблема в том, что это вообще не оживляет и показывает излучатель в его окончательном положении. У меня сложилось впечатление, что, как только вы добавите анимацию к слою, вы должны изменить фактическую модель позади нее в ее конечное положение, чтобы после завершения анимации модель находилась в своем конечном состоянии; то есть, чтобы анимация не "вернулась назад" в исходное положение.

Я попытался поместить последние две строки в animation.completion блок, и это действительно оживляет, как и ожидалось. Однако, когда анимация заканчивается, некоторые частицы периодически испускаются в исходном положении излучателя. Если вы загружаете систему (например, прокручиваете таблицу во время воспроизведения анимации), это происходит чаще.

Другое решение, о котором я думал, это не двигать emitterPosition на все, но просто переместите CAEmitterLayer сам, хотя я еще не пробовал.

Заранее благодарим за любую помощь, которую вы можете предоставить.

1 ответ

Решение

Возможно emitterPosition.x не является допустимым ключевым путем для анимации. Попробуйте использовать emitterPosition вместо этого (и поэтому вы должны будете предоставить значения CGPoint, обернутые в NSValue).

Я только что попробовал это на моей собственной машине, и она отлично работает:

CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"emitterPosition"];
ba.fromValue = [NSValue valueWithCGPoint:CGPointMake(30,100)];
ba.toValue = [NSValue valueWithCGPoint:CGPointMake(200,100)];
ba.duration = 6;
ba.autoreverses = YES;
ba.repeatCount = HUGE_VALF;
[emit addAnimation:ba forKey:nil];

Другие вещи, чтобы думать о:

  • Обычно вы можете использовать ноль в качестве ключа в addAnimation:forKey:, если вам не понадобится найти эту анимацию позже (например, чтобы удалить или переопределить ее каким-либо образом). Ключевой путь - важная вещь.

  • настройка removedOnCompletion НЕТ почти всегда неверно и обычно является последним прибежищем негодяя (т.е. из-за непонимания того, как работает анимация).

  • Если, как вы говорите, настройка _emitterLayer.emitterPosition = newEmitterPosition внутри блока завершения происходит анимация, тогда когда вы вообще используете CABasicAnimation? Почему бы просто не позвонить UIView animate... и установить emitterPosition в блоке анимации? Если это сработает, это убьет двух зайцев одним движением, сдвинув позицию и оживив ее тоже.

Другие вопросы по тегам