我正试图像这样CAEmitterLayer
的{{1}}动画:
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
本身,尽管我还没有尝试过。
提前感谢您提供的任何帮助。
答案 0 :(得分:6)
也许emitterPosition.x
不是动画的有效关键路径。请尝试使用emitterPosition
(因此您必须提供包含在NSValue中的CGPoint值)。
我只是在我自己的机器上试过这个并且它工作正常:
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];
要考虑的其他事项:
您通常可以使用nil作为addAnimation:forKey:
中的键,除非您以后需要找到此动画(例如删除它或以某种方式覆盖它)。关键路径是重要的。
将removedOnCompletion
设置为NO几乎总是错误的,通常是恶棍的最后避难所(即由于不了解动画的工作方式)。
如果正如您所说,在完成块内设置_emitterLayer.emitterPosition = newEmitterPosition
会设置动画,那么为什么要使用CABasicAnimation?为什么不调用UIView animate...
并在动画块中设置emitterPosition?如果这样可行的话,它将一石二鸟,移动位置并为其制作动画。