CABasicAnimation и пользовательские типы

Я не очень знаком с CoreAnimation, поэтому я надеюсь, что я просто пропустил что-то довольно простое. Я хочу анимировать пользовательское свойство (NSGradient) NSView в простой форме, с [[view animator] setGradient:gradient];, Я определил + (id)defaultAnimationForKey:(NSString *)key и вернул простую CABasicAnimation, однако анимация не выполняется. Так как это работает для простых типов и NSColor, я думаю, что CABasicAnimation не работает с градиентами. Хорошо, но в данном конкретном случае градиенты тривиальны (всегда две остановки), поэтому я легко могу написать интерполяционные функции. Вопрос: как я могу определить пользовательскую интерполяцию? Я гуглил по поводу делегатов по представлению, слою и анимации, по подклассам класса анимации и т. Д., Но я не смог разобраться. Спасибо!

1 ответ

Решение

Мне показалось, что я вспомнил про прохождение некоторой документации Apple, когда я изучал, как использовать Core Animation, которая показывала, как настроить анимации, которые не могут быть обработаны описаниями Properticode, которые поставляются с определенными анимациями. По пути я наткнулся на некоторый пример кода от Apple, который описывается как:

Один градиентный слой отображается и непрерывно анимируется с использованием новых случайных цветов.

Это может быть ответом на конкретную задачу, которую вы уже выполнили другим способом. Я нашел это в Документации и Справочнике по API в XCode, и имя образца кода просто Градиенты. (Обратите внимание, что существует оригинальная версия 1.0 и обновленная версия 1.1, которая была переделана в этом году в апреле и поэтому должна быть проще в использовании с текущими инструментами.

Но основной вопрос создания пользовательской анимации, которая не может быть автоматизирована самой Core Animation, заключается в том, чтобы последовать примеру из Руководства Apple по программированию анимации для какао в разделе Использование объекта NSAnimation. Он описан в разделе " Создание подклассов NSAnimation", а рекомендуемый метод показан под заголовком " Плавные анимации". Вы отменяете setCurrentProgress: метод, чтобы каждый раз, когда он вызывается, вы сначала вызываете Super так что NSAnimation обновляет значение прогресса, т. е. ваше пользовательское анимированное свойство, а затем выполняет любое обновление или рисование, необходимые для следующего кадра вашей анимации. Вот примечания и пример кода, предоставленные Apple в указанной документации:

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

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

Listing 4  Overriding the setCurrentProgress: method
- (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 запускать анимацию, используя обычные методы настройки анимации, и он выполнит ваш код, чтобы нарисовать каждый кадр анимации в соответствующее время.

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

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