Есть ли способ запустить 2 объекта NSAnimation одновременно?

Я создал 2 NSAnimation объекты переворачивания представления с другим представлением. Я хотел бы запустить 2 эти анимации одновременно. Я не могу использовать NSViewAnimation, поскольку теперь речь идет об анимации любого из свойств представления.

Вот создание анимации:

self.animation = [[[TransitionAnimation alloc] initWithDuration:1.0 animationCurve:NSAnimationEaseInOut] autorelease];
[self.animation setDelegate:delegate];
[self.animation setCurrentProgress:0.0];

[self.animation startAnimation];

Я пытался связать 2 анимации, но, возможно, по какой-то причине это не сработало. Я взял пример с: сайта разработчика Apple

настройка NSAnimation объект для использования NSAnimationNonblocking не показывает анимацию вообще...

РЕДАКТИРОВАТЬ: вторая анимация точно так же, как первая и создается в том же месте, где создается первая.

TransitionAnimation это подкласс NSAnimation, где setCurrentProgress выглядит так:

- (void)setCurrentProgress:(NSAnimationProgress)progress {
    [super setCurrentProgress:progress];
    [(NSView *)[self delegate] display];    
}

delegate является NSView в этом случае, который в своей функции drawRect применяет зависящий от времени CIFilter на CIImage, Проблема в том, что он работает синхронно, и вторая анимация начинается сразу после окончания первой. Есть ли способ запустить их одновременно?

1 ответ

Решение

NSAnimation на самом деле не лучший выбор для анимации нескольких объектов и их свойств одновременно.

Вместо этого вы должны привести свои взгляды в соответствие с NSAnimatablePropertyContainer протокол.

Затем вы можете настроить несколько пользовательских свойств в качестве анимируемых (в дополнение к свойствам, уже поддерживаемым NSView), а затем вы можете просто использовать свои взгляды animator прокси для анимации свойств:

yourObject.animator.propertyName = finalPropertyValue;

Помимо упрощения анимации, она также позволяет анимировать несколько объектов одновременно, используя NSAnimationContext:

[NSAnimationContext beginGrouping];
firstObject.animator.propertyName = finalPropertyValue1;
secondObject.animator.propertyName = finalPropertyValue2;
[NSAnimationContext endGrouping];

Вы также можете установить продолжительность и предоставить блок обработчика завершения:

[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0.5];
[[NSAnimationContext currentContext] setCompletionHandler:^{
    NSLog(@"animation finished");
}];
firstObject.animator.propertyName = finalPropertyValue1;
secondObject.animator.propertyName = finalPropertyValue2;
[NSAnimationContext endGrouping];

NSAnimation а также NSViewAnimation классы намного старше, чем поддержка прокси аниматора, и я настоятельно рекомендую вам отойти от них, если это возможно. Поддерживая NSAnimatablePropertyContainer Протокол намного проще, чем управлять всеми NSAnimation делегировать вещи. Поддержка Lion для пользовательских функций синхронизации и обработчиков завершения означает, что больше нет необходимости делать это.

Для стандарта NSView объект, если вы хотите добавить поддержку анимации для свойства в вашем представлении, вам просто нужно переопределить +defaultAnimationForKey: метод на ваш взгляд и вернуть анимацию для свойства:

//declare the default animations for any keys we want to animate
+ (id)defaultAnimationForKey:(NSString *)key
{
    //in this case, we want to add animation for our x and y keys
    if ([key isEqualToString:@"x"] || [key isEqualToString:@"y"]) {
        return [CABasicAnimation animation];
    } else {
        // Defer to super's implementation for any keys we don't specifically handle.
        return [super defaultAnimationForKey:key];
    }
}

Я создал простой пример проекта, который показывает, как анимировать несколько свойств представления одновременно, используя NSAnimatablePropertyContainer протокол.

Все, что нужно для успешного обновления, - это убедиться, что setNeedsDisplay:YES Вызывается, когда любое из анимируемых свойств изменяется. Затем вы можете получить значения этих свойств в вашем drawRect: метод и обновить анимацию на основе этих значений.

Если вам нужно простое значение прогресса, аналогичное тому, как все работает NSAnimation Вы могли бы определить progress Свойство на ваш взгляд, а затем сделать что-то вроде этого:

yourView.progress = 0;
[yourView.animator setProgress:1.0];

Вы можете получить доступ self.progress в вашем drawRect: Метод, чтобы узнать текущее значение анимации.

Другие вопросы по тегам