替代使用CABasicAnimation回调?
CAAnimation不提供分配除标准“animationDidStart:”/“animationDidStop:”方法之外的回调函数的机制。
我有一个自定义的UIControl,它使用了两个重叠的CALayers。 这种控制的目的类似于一个老式的声纳。 顶层的内容包含一个不断旋转的图像(称之为“魔杖”)。 该层下面是一个“spriteControl”层,当魔杖越过它们时呈现闪烁。
这些blips代表的对象被spriteControl预取并组织成不可见的CAShapeLayers。 我正在使用CABasicAnimation一次旋转魔杖10度,然后利用“animationDidStop:”方法调用spriteControl上的一个方法,该方法使用魔杖图层的当前旋转值(又称为标题),并将Alpha设置的动画设置为1.0到0.0用于模拟闪烁和淡出效果。 最后,这个过程无限期地重新开始。
尽管使用CAAnimation回调的这种方法确保了棒到达“ping”位置(即,10deg,20deg,270deg等)的时间总是与另一层中的blip的发光一致,但是存在停止,重新计算并每10度开始一次动画。
我可以产生一个NSTimer来激发一个方法来查询魔杖表示层的角度来获取标题值。 然而,这使得难以保持魔杖和blip突出显示同步,并且/或者导致一些完全跳过。 这个方法在这里讨论一下:我如何回调CABasicAnimation动画?
所以我的问题是,如果不使用OpenGL ES重新实现控制,是否有任何事情可以提高棒图层旋转的性能。 (我意识到这可以在OpenGL环境中轻松解决,但是,在这里使用它需要进行大量的重新设计,这是不值得的。)虽然性能问题很小,但我不能动摇那种感觉简单而明显的是,我可以做到这一点将允许魔杖无限期地动画,而不会暂停执行昂贵的旋转计算。
这是一些代码:
- (void)rotateWandByIncrement
{
if (wandShouldStop)
return;
CGFloat newRotationDegree = (wandRotationDegree + WAND_INCREMENT_DEGREES);
if (newRotationDegree >= 360)
newRotationDegree = 0;
CATransform3D rotationTransform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(newRotationDegree), 0, 0, 1);
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform"];
animation.toValue = [NSValue valueWithCATransform3D:rotationTransform];
animation.duration = WAND_INCREMENT_DURATION;
animation.fillMode = kCAFillModeForwards;
animation.removedOnCompletion = FALSE;
animation.delegate = self;
[wandLayer addAnimation:animation forKey:@"transform"];
}
- (void)animationDidStart:(CAAnimation *)theAnimation
{
if (wandShouldStop)
return;
NSInteger prevWandRotationDegree = wandRotationDegree - WAND_INCREMENT_DEGREES;
if (prevWandRotationDegree < 0)
prevWandRotationDegree += 360;
// Pulse the spriteControl
[[self spriteControl] pulseRayAtHeading:prevWandRotationDegree];
}
- (void)animationDidStop:(CAAnimation *)theAnimation finished:(BOOL)flag
{
// update the rotation var
wandRotationDegree += WAND_INCREMENT_DEGREES;
if (wandRotationDegree >= 360)
wandRotationDegree = 0;
// This applies the rotation value to the model layer so that
// subsequent animations start where the previous one left off
CATransform3D rotationTransform = CATransform3DMakeRotation(DEGREES_TO_RADIANS(wandRotationDegree), 0, 0, 1);
[CATransaction begin];
[CATransaction setDisableActions:TRUE];
[wandLayer setTransform:rotationTransform];
[CATransaction commit];
//[wandLayer removeAnimationForKey:@"transform"];
[self rotateWandByIncrement];
}
假设雷达需要10秒完成一次完整的旋转。
为了让魔杖无限期地旋转,请将其Duration
属性设置为10并将其RepeatCount
属性设置为1e100f的CABasicAnimation
附加到它。
可以使用他们自己的实例CAKeyframeAnimation
进行动画CAKeyframeAnimation
。 我不会写详细信息,但是对于每个blip,您都指定一个不透明度值的数组(我认为不透明度是您如何淡出blipped)和一系列时间百分比(请参阅Apple的文档)。