2013-03-13 56 views
0

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

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]; 

回答

1

通常可以观察到类似位置的特性,例如,很容易使用定时器或显示器连接,而在动态画面的运行,但是,因为它是你想监控的内容属性,事情不大更棘手。我建议你动画你自己的自定义属性。然后,您可以将其与现有内容动画一起在组中制作动画,并在您的自定义属性更改时获取更新。

的步骤去是这样的:

  1. 声明一个CALayer的派生类
  2. 重写这些方法:

    - (id)initWithLayer:(id)layer

    + (BOOL)needsDisplayForKey:(NSString*)key

    - (void)drawInContext:(CGContextRef)ctx

  3. 创建要在头

  4. 覆盖创建一个关键帧动画动画你的财产

这里的财产是你的层可能是什么样子在其实施:

@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特定的代码。

+0

感谢您的真棒回答!我需要在OS X上测试它,但是当我使用iOS 6.1模拟器尝试github repo时,它会为每张幻灯片记录约20次相同的计数器值。你注意到了吗? – dbainbridge 2013-03-15 14:31:42

+0

是的。 drawInContext正在以图层的帧速率调用。你必须观察*计数器值的变化*。 – 2013-03-15 16:06:51

0

哇,这是一个伟大的工作!我会用它...

只需要注意一点,我在Xcode 5上,我发现只有第一个动画“slideShowAnimation”被激发。

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

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

感谢分享。 - nIc