检测CAKeyframeAnimation中显示的帧

时间:2013-03-13 23:49:52

标签: core-animation cakeyframeanimation

我需要显示有关通过CAKeyframeAnimation显示的当前fey帧图像的信息。因此,当显示“值”索引0处的图像时,在某些NSTextField中显示关于该图像的信息,并且当它动画到索引1时显示关于该图像的信息。是否有可能做到这一点?

CAKeyframeAnimation *theAnimation=[CAKeyframeAnimation animationWithKeyPath:@"contents"];
theAnimation.values = myView.productImages;
theAnimation.duration = 5.0;
theAnimation.repeatCount = HUGE_VALF;
theAnimation.calculationMode = kCAAnimationDiscrete;
theAnimation.fillMode = kCAFillModeRemoved;
[myView.exampleCALayer addAnimation:theAnimation forKey:@"contents"];
[myView.exampleCALayer setNeedsDisplay];

2 个答案:

答案 0 :(得分:1)

通常情况下,您可以观察位置等属性,例如,在动画运行时很容易使用计时器或显示链接,但是,因为它是您要监视的内容属性,所以事情变得更加棘手。我建议您为自己的自定义属性设置动画。然后,您可以在组中为其添加动画以及现有内容动画,并在自定义属性更改时获取更新。

步骤如下:

  1. 声明CALayer派生类
  2. 覆盖这些方法:

    - (id)initWithLayer:(id)layer

    + (BOOL)needsDisplayForKey:(NSString*)key

    - (void)drawInContext:(CGContextRef)ctx

  3. 在标题

  4. 中创建要覆盖的属性
  5. 创建动画属性的关键帧动画
  6. 以下是您的图层在其实现中的外观:

    @implementation MLImageLayer
    
    - (id)initWithLayer:(id)layer
    {
        if(self = [super initWithLayer:layer]) {
            if([layer isKindOfClass:[MLImageLayer class]]) {
                MLImageLayer *other = (MLImageLayer*)layer;
          [self setCounter:[other counter]];
            }
        }
        return self;
    }
    
    + (BOOL)needsDisplayForKey:(NSString*)key
    {
      if ([key isEqualToString:@"counter"]) {
        return YES;
      } else {
        return [super needsDisplayForKey:key];
      }
    }
    
    - (void)drawInContext:(CGContextRef)ctx
    {
      DLog(@"Counter is: %d", _counter);
    }
    
    @end
    

    然后,要实际为该属性设置动画,请执行以下操作:

      CAKeyframeAnimation *counterAnimation = [CAKeyframeAnimation 
                                                  animationWithKeyPath:@"counter"];
      [counterAnimation setDelegate:self];
      NSArray *values = @[@(0), @(1), @(2), @(3), @(4), @(5)];
      [counterAnimation setValues:values];
      [counterAnimation setDuration:5.0];
      [counterAnimation setRepeatCount:HUGE_VALF];
      [counterAnimation setCalculationMode:kCAAnimationDiscrete];
    

    现在,回到派生图层的-drawInContext:方法中,您可以监视计数器值,然后做出相应的响应。

    但是,这可能有点棘手,因为您同时为两个属性设置了动画。您必须使用一组来使其正常工作:

    - (void)viewDidLoad
    {
      [super viewDidLoad];
    
      _animationLayer = [MLImageLayer layer];
      [_animationLayer setBounds:CGRectMake(0.0f, 0.0f, 400.0f, 320.0f)];
      [_animationLayer setPosition:[[self view] center]];
    
      UIImage *image = [UIImage imageNamed:@"Countryside.jpg"];
      [_animationLayer setContents:(__bridge id)[image CGImage]];
    
      [[[self view] layer] addSublayer:_animationLayer];
    
      CAKeyframeAnimation *slideShowAnimation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
      [slideShowAnimation setValues:@[(id)[[UIImage imageNamed:@"Countryside.jpg"] CGImage],
       (id)[[UIImage imageNamed:@"Countryside-1.jpg"] CGImage],
       (id)[[UIImage imageNamed:@"Countryside-2.jpg"] CGImage],
       (id)[[UIImage imageNamed:@"Countryside-3.jpg"] CGImage],
       (id)[[UIImage imageNamed:@"Countryside-4.jpg"] CGImage],
       (id)[[UIImage imageNamed:@"Countryside-5.jpg"] CGImage]]];
    
      [slideShowAnimation setDuration:5.0];
      [slideShowAnimation setDelegate:self];
      [slideShowAnimation setRepeatCount:HUGE_VALF];
      [slideShowAnimation setCalculationMode:kCAAnimationDiscrete];
    
      CAKeyframeAnimation *counterAnimation = [CAKeyframeAnimation animationWithKeyPath:@"counter"];
      [counterAnimation setDelegate:self];
      NSArray *values = @[@(0), @(1), @(2), @(3), @(4), @(5)];
      [counterAnimation setValues:values];
      [counterAnimation setDuration:5.0];
      [counterAnimation setRepeatCount:HUGE_VALF];
      [counterAnimation setCalculationMode:kCAAnimationDiscrete];
    
      CAAnimationGroup *group = [CAAnimationGroup animation];
      [group setDuration:5.0];
      [group setRepeatCount:HUGE_VALF];
      [group setAnimations:@[slideShowAnimation, counterAnimation]];
    
      [_animationLayer addAnimation:group forKey:nil];
    }
    

    我发布了一个项目up on github。它是为iOS编写的,但您应该能够在OSX应用程序中调整Core Animation特定代码。

答案 1 :(得分:0)

哇,这太棒了!!!我会用它......

只有一个注释,我在Xcode 5上,我注意到只有第一个动画“slideShowAnimation”被触发。

我可以通过添加以下两行来修复它:

[slideShowAnimation setBeginTime:0];
[counterAnimation setBeginTime:0];

感谢分享。 - nIc