Используя объект NSAnimation

NSAnimation класс обеспечивает сложное поведение для анимаций, происходящих за конечный отрезок времени. OS X использует объекты Animation для реализации анимаций перехода для элементов пользовательского интерфейса. Можно определить объекты пользовательской анимации реализовать анимации для собственного кода. В отличие от этого NSTimer, уведомления анимации могут произойти в неправильных интервалах, позволив Вам создать анимации, которые, кажется, убыстряются или замедляются.

Следующие разделы покрывают основные шаги для создания пользовательского NSAnimation объект и использование его для управления анимированным контентом. Если Вы хотите анимировать свои представления и окна, необходимо видеть если NSViewAnimation класс (который является подклассом NSAnimation) предложите поведение, в котором Вы нуждаетесь. Просмотрите объекты Animation, обеспечивают сложное поведение для изменения размеров и перемещения представлений в течение долгого времени и описаны в Анимации Представлений и Windows.

Создание и конфигурирование таймера анимации

NSAnimation объект имеет несколько важных атрибутов:

Когда Вы конфигурируете новое NSAnimation объект, необходимо, как минимум, установить его продолжительность, кривую анимации, частоту кадров и атрибуты режима блокирования. Необходимо также присвоить делегата для контроля динамики анимации. Когда анимация начинается, заканчивается, явно останавливается или достигает метки прогресса, объект Animation отправляет сообщение текущему делегату. (См. Установку и Обработку Знаков Прогресса для получения информации о метках прогресса). Если Вы не хотите использовать делегата, необходимо разделить на подклассы NSAnimation получить информацию о прогрессе; посмотрите Разделение на подклассы NSAnimation.

Перечисление 1 показывает выборочный метод, создающий и конфигурирующий стандарт NSAnimation объект. Объект, создавший действия анимации как делегата и обрабатывающий любые сообщения о ходе выполнения.

Перечисление 1  , Инициализирующее объект NSAnimation

- (id)init
{
    self = [super init];
    if (self)
    {
        // theAnim is an NSAnimation instance variable.
        theAnim = [[NSAnimation alloc] initWithDuration:10.0
                                     animationCurve:NSAnimationEaseIn];
        [theAnim setFrameRate:20.0];
        [theAnim setAnimationBlockingMode:NSAnimationNonblocking];
        [theAnim setDelegate:self];
    }
    return self;
}

initWithDuration:animationCurve: метод является определяемым инициализатором для NSAnimation класс. Этот метод позволяет Вам установить два из атрибутов анимации. Для других атрибутов можно использовать значения по умолчанию или установить значение атрибута явно с помощью надлежащих методов доступа. Атрибуты по умолчанию следующие:

Как только Вы подготовились NSAnimation объект для использования, можно выполнить его путем отправки ему a startAnimation сообщение. Если необходимо остановить его, прежде чем анимация завершит свою запланированную продолжительность, отправьте объект a stopAnimation сообщение. Делегат NSAnimation объект (если Вы существуете) получает сообщения, сообщающие ему об обоих из этих событий, а также сообщению, говорящему его, если анимация завершилась, как запланировано.

Установка и обработка Знаков прогресса

NSAnimation имеет понятие меток прогресса — значения с плавающей точкой (типа NSAnimationProgress) это указывает сумму процента анимации, которая завершена. Когда Вы запускаете анимацию, и она достигает метки прогресса (в частности, ее текущий прогресс равен метке прогресса), объект Animation отправляет сообщение своему делегату. Делегат может тогда обновить пользовательский индикатор хода выполнения, играть звук или выполнить некоторый другой эффект, надлежащий той точке анимации.

Когда Вы сначала создаете и инициализируете объект, обычно Вы устанавливаете метки прогресса объекта Animation. Перечисление 2 показывает один подход, устанавливающий 20 равномерно распределенных меток прогресса.

Перечисление 2  , Устанавливающее метки прогресса объекта NSAnimation

- (void)awakeFromNib
{
     NSAnimationProgress progMarks[] = {
            0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5,
            0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0  };
 
    int i, count = 20;
    // theAnim is an NSAnimation instance variable
    theAnim = [[NSAnimation alloc] initWithDuration:10.0
                                animationCurve:NSAnimationEaseInOut];
    [theAnim setFrameRate:20.0];
    [theAnim setDelegate:self];
 
    for (i=0; i<count; i++)
        [theAnim addProgressMark:progMarks[i]];
}

Вместо того, чтобы добавить метку прогресса оценивает в цикле, как в этом примере, можно установить их в одном вызове при помощи setProgressMarks: метод, берущий массив NSNumber инкапсуляция объектов float значения.

Когда рабочий объект Animation достигает метки прогресса, он отправляет animation:didReachProgressMark: обменивайтесь сообщениями его делегату. Делегат должен обработать это сообщение в пути, надлежащем метке прогресса, переданной в. Перечисление 3 иллюстрирует, как делегат реализует этот метод для игры звука поезда равномерно.

  Делегат перечисления 3 реализация animation:didReachProgressMark:

- (void)animation:(NSAnimation *)animation
            didReachProgressMark:(NSAnimationProgress)progress
{
    if (animation == theAnim)
        [[NSSound soundNamed:@"chug"] play];
}

Разделение на подклассы NSAnimation

Несмотря на то, что можно использовать NSAnimation возразите как есть во многих целях, разделение на подклассы его является более общим сценарием. Существует три основных причины разделить на подклассы NSAnimation:

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

Плавные анимации

Как упомянуто в Установке и Обработке Знаков Прогресса, можно присоединить серию меток прогресса к NSAnimation возразите и сделайте, чтобы делегат реализовал animation:didReachProgressMark: метод для перерисовки объекта в каждой метке прогресса. Однако это не лучший способ анимировать объект. Если Вы не определяете большой номер меток прогресса (30 в секунду или больше), анимация, вероятно, собирается казаться судорожной.

Лучший подход должен разделить на подклассы NSAnimation и переопределение setCurrentProgress: метод, как проиллюстрировано в Перечислении 4. NSAnimation объект вызывает этот метод после каждого кадра для изменения значения прогресса. Путем прерывания этого сообщения можно выполнить любую перерисовку, или обновление Вас нуждаются для того кадра. Если Вы действительно переопределяете этот метод, несомненно, вызовут реализацию super так, чтобы это могло обновить текущий прогресс.

Перечисление 4  , Переопределяющее setCurrentProgress: метод

- (void)setCurrentProgress:(NSAnimationProgress)progress
{
    // Call super to update the progress value.
    [super setCurrentProgress:progress];
 
    // Update the window position.
    NSRect theWinFrame = [[NSApp mainWindow] frame];
    NSRect theScreenFrame = [[NSScreen mainScreen] visibleFrame];
    theWinFrame.origin.x = progress *
            (theScreenFrame.size.width - theWinFrame.size.width);
    [[NSApp mainWindow] setFrame:theWinFrame display:YES animate:YES];
}

Пользовательские наборы режима цикла выполнения

NSAnimation объект с режимом блокирования NSAnimationNonblocking выполнения в основном потоке процесса в режиме цикла выполнения, принимающем ввод данных пользователем. Прежде чем это выполнит анимацию, объект Animation отправляет себе a runLoopModesForAnimation сообщение для получения в настоящее время допустимых режимов цикла выполнения. По умолчанию, этот метод возвраты nil, который говорит NSAnimation использовать режим по умолчанию (NSDefaultRunLoopMode), модальный режим панели (NSModalPanelRunLoopMode), и событие, отслеживающее режим цикла выполнения (NSEventTrackingRunLoopMode).

Можно переопределить этот метод для возврата различного набора выполненных режимов цикла, которые могут включать пользовательские режимы. Перечисление 5 показывает реализацию, возвращающую массив по умолчанию режимов минус режим отслеживания события (NSEventTrackingRunLoopMode).

Перечисление 5  Возвращая режимы цикла выполнения из runLoopModesForAnimating

- (NSArray *)runLoopModesForAnimating
{
    return [NSArray arrayWithObjects: NSDefaultRunLoopMode,
                         NSModalPanelRunLoopMode, nil];
}

Соединение анимаций

Можно соединить два объекта Animation так, чтобы один из них начал работать (или прекращает работать), когда другие пределы указанная метка анимации. Эта функция NSAnimation полезно для координирования различных эффектов. Перечисление 6 иллюстрирует как startWhenAnimation:reachesProgress: когда другая анимация достигает промежуточного этапа, метод используется для запуска анимации.

Перечисление 6  , Соединяющее две анимации

- (IBAction)startAnim:(id)sender
{
    // theAnim and theOtherAnim are variables of type NSAnimation.
    [theOtherAnim startWhenAnimation:theAnim reachesProgress:0.5];
    [theAnim startAnimation];
}

Если Вы хотите вместо этого остановить анимацию, когда другая анимация достигает метки прогресса, используйте stopWhenAnimation:reachesProgess: метод. Можно соединить анимации неопределенно, один за другим. Однако может быть, только один «запускается» и одна анимация «остановки» в любой момент времени.

Если у Вас есть делегат, отвечающий на animation:didReachProgressMark: сообщения, это должно различить среди многократных анимаций, как в Перечислении 7.

Перечисление 7  , Обрабатывающее метки прогресса одновременно рабочих анимаций

- (void)animation:(NSAnimation *)animation
            didReachProgressMark:(NSAnimationProgress)progress
{
    if (animation == theOtherAnim)
    {
        // Do an effect appropriate to progress mark.
    }
    else if (animation == theAnim)
    {
        // Do an effect appropriate to progress mark.
    }
}