0

除了标准的“animationDidStart:”/“animationDidStop:”方法之外,CAAnimation 不提供分配回调函数的机制。

我有一个自定义 UIControl,它使用了 2 个重叠的 CALayers。这种控制的目的类似于老式的声纳。顶层的内容包含一个不断旋转的图像(将此层称为“魔杖”)。在该层之下是一个“spriteControl”层,当魔杖经过它们时会呈现光点。

blips 表示的对象由 spriteControl 预取并组织成不可见的 CAShapeLayers。我正在使用 CABasicAnimation 一次将魔杖旋转 10 度,然后利用“animationDidStop:”方法调用 spriteControl 上的一个方法,该方法采用魔杖层的当前旋转值(又名标题)并从1.0 到 0.0 用于模拟闪烁和淡出效果。最后,该过程无限期地重新开始。

虽然这种使用 CAAnimation 回调的方法确保了魔杖到达“ping”位置(即 10 度、20 度、270 度等)的时间始终与另一层中光点的照明一致,但存在停止的问题,重新计算,每 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];
}
4

1 回答 1

1

假设雷达旋转一圈需要 10 秒。

要让魔杖无限旋转,请将 a 附加CABasicAnimation到它,并将其Duration属性设置为 10,并将其RepeatCount属性设置为 1e100f。

每个 blip 都可以使用它们自己的实例进行动画处理CAKeyframeAnimation。我不会写详细信息,但是对于每个 blip,您指定一组不透明度值(我假设不透明度是您淡出 blip 的方式)和一组时间百分比(请参阅 Apple 的文档)。

于 2011-05-04T01:58:51.593 回答