跟踪核心动画动画

时间:2010-11-25 00:12:28

标签: cocoa-touch core-animation

我有两个围绕屏幕移动的圆圈。圆圈都是包含其他UIViews的UIViews。每个圆圈外面的区域都是透明的。

我编写了一个函数来创建一个CGPath,它将两个圆形连接成四边形。我在透明的CALayer中填充此路径,该CALayer跨越整个屏幕。由于该层位于两个圆形UIViews的后面,因此它似乎可以连接它们。

最后,两个UIViews使用Core Animation进行动画制作。在此动画期间,两个圆圈的位置和大小会发生变化。

到目前为止,我唯一获得成功的方法是使用NSTimer定期中断动画,然后根据圆圈presentationLayer的位置重新计算并绘制光束。但是,当动画加速时,四边形滞后于

使用Core Animation有更好的方法吗?或者我应该避免使用Core Animation并使用NSTimer实现我自己的动画吗?

2 个答案:

答案 0 :(得分:13)

我遇到了类似的问题。我使用了图层而不是动画的视图。你可以尝试这样的事情。

  1. 将每个元素绘制为CALayer,并将它们包含为容器UIVIew图层的子图层。 UIViews更容易制作动画,但你的控制力会减少。请注意,对于任何视图,您都可以使用[view layer]获取它的图层;
  2. 为您的四边形创建自定义子图层。此图层应具有要为此图层设置动画的属性或多个属性。我们称这个属性为“customprop”。由于它是自定义图层,因此您需要在动画的每个帧上重绘。对于您计划设置动画的属性,您的自定义图层类应返回YES needsDisplayForKey:。这样你就可以确保在每一帧都调用 - (void)drawInContext:(CGContextRef)theContext
  3. 将所有动画(圆圈和四边形)放在同一个交易中;

  4. 对于圈子,您可以使用CALayers并设置内容,如果是图像,则采用标准方式:

    layer.contents = [UIImage imageNamed:@"circle_image.png"].CGImage;
    

    现在,对于四层,子类CALayer并以这种方式实现:

    - (void)drawInContext:(CGContextRef)theContext{
      //Custom draw code here
    }   
    + (BOOL)needsDisplayForKey:(NSString *)key{
       if ([key isEqualToString:@"customprop"])
          return YES;
        return [super needsDisplayForKey:key];
    }   
    

    交易看起来像:

    [CATransaction begin];
    CABasicAnimation *theAnimation=[CABasicAnimation animationWithKeyPath:@"customprop"];
    
    theAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(1000, 1000)];
    theAnimation.duration=1.0;
    theAnimation.repeatCount=4;
    theAnimation.autoreverses=YES;
    theAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseIn];
    theAnimation.delegate = self;
    [lay addAnimation:theAnimation forKey:@"selecting"];
    
    [CATransaction setValue:[NSNumber numberWithFloat:10.0f]
                         forKey:kCATransactionAnimationDuration];
    circ1.position=CGPointMake(1000, 1000);
    circ2.position=CGPointMake(1000, 1000);
    [CATransaction commit];
    

    现在所有的绘制程序都会同时发生。确保你的drawInContext:实现很快。否则动画会滞后。

    将每个子图层添加到UIViews的图层后,记住调用[layer setNeedsDisplay]。它不会自动调用。

    我知道这有点复杂。但是,生成的动画比使用NSTimer并重新绘制每次调用更好。

答案 1 :(得分:1)

如果您需要查找图层的当前可见状态,可以在相关的CALayer上调用-presentationLayer,这将为您提供一个近似于用于渲染的图层。注意我说的近似 - 它不能保证完全准确。但是,它可能足以满足您的目的。