2013-03-13 2 views
0

Мне нужно отобразить информацию о текущем изображении фей-кадра, которое отображается с помощью CAKeyframeAnimation. Поэтому, когда изображение с индексом «значения» отображается 0, отображается информация в некоторых NSTextFields об этом изображении, и когда он анимируется в индекс 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. Override эти методы:

    - (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, но вы должны иметь возможность адаптировать специальный код Core Animation в приложении OSX.

+0

Спасибо за отличный ответ! Мне нужно протестировать его на OS X, но когда я попробовал ретрансляцию github с помощью симулятора iOS 6.1, он будет регистрировать одинаковое значение счетчика примерно 20 раз для каждого слайда.Вы заметили это? – dbainbridge

+0

Да. Ваш drawInContext вызывается на частоте кадров слоя. Вам нужно будет следить за * изменениями * в значение счетчика. –

0

Ничего себе, это отличная работа !!! Я буду использовать его ...

Только одно примечание, я на Xcode 5, и я заметил, что только первая анимация «slideShowAnimation» запущена.

Я мог бы это исправить, просто добавив эти две строки:

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

Спасибо за обмен. - nIc

Смежные вопросы