Если вы являетесь разработчиком Silverlight или WPF, то вы уже хорошо знаете концепцию раскадровки. Это элемент, который позволяет вам выполнять анимацию и переходы пользовательского интерфейса, не беспокоясь о «слесарной» части процесса, где вам фактически приходится кодировать анимацию и движение объекта. Теперь, с выходом Windows 8, вы можете создавать приложения XAML, основанные на C ++ / Cx, и, несмотря на тот факт, что вы все еще придерживаетесь той же идеи, некоторые части забавного раскадровки отличаются.
Допустим, у вас есть этот сценарий:
- Вы хотите использовать раскадровку
- Вы хотите использовать DoubleAnimationUsingKeyFrames
- Вам нужен LinearDoubleKeyFrame
XAML для этого не выглядит слишком плохо. Но как насчет кода позади? В некоторых случаях вам необходимо динамически создавать и изменять анимацию. Создание раскадровки само по себе не очень сложно:
Storyboard^ yourStoryboard = ref new Storyboard(); yourStoryboard ->Duration = DurationHelper::Forever;
Здесь я просто создаю новый экземпляр Storyboard и устанавливаю фиксированную продолжительность. Очевидно, что вы можете установить пользовательское значение для этого свойства, но об этом чуть позже. На данный момент у вас есть фундаментальный блок для динамической анимации.
Теперь вам нужен экземпляр DoubleAnimationUsingKeyFrames, который будет обрабатывать детали действий на основе ключевых кадров.
DoubleAnimationUsingKeyFrames^ doubleAnimation = ref new DoubleAnimationUsingKeyFrames(); TimeSpan span = TimeSpan(); span.Duration = 0; doubleAnimation->BeginTime = span;
Здесь время начала устанавливается каждый раз, когда раскадровка активируется — точка ноль, поэтому 0: 0: 0 в значениях XAML. Следующий шаг — добавление LinearDoubleKeyFrame. Но перед этим вам нужно убедиться, что DoubleAnumationUsingKeyFrames знает, что нужно анимировать. Для этого примера у меня есть элемент управления TextBlock с TranslateTransform.
Однако, поскольку он устанавливается через RenderTransform и является единственным используемым преобразованием, я могу ссылаться на него через (RenderTransform) .X , где X показывает, что я перемещаю элемент управления по оси X.
Storyboard::SetTarget(doubleAnimation,yourTextBlock); Storyboard::SetTargetProperty(doubleAnimation,"(RenderTransform).X");
Очевидно, вы можете настроить это для различных преобразований, которые вы используете в вашем случае. Давайте перейдем к ключевым кадрам, и мы начнем с LinearDoubleKeyFrame.
LinearDoubleKeyFrame^ kf = ref new LinearDoubleKeyFrame(); kf->Value = 20; TimeSpan span = TimeSpan(); span.Duration = 5000000; kf->KeyTime = KeyTime(span); doubleAnimation->KeyFrames->Append(kf);
Когда этот ключевой кадр станет активным, он переместит мой TextBlock вправо от оси X, учитывая положительное значение, которое я установил для свойства Value. Это цель, которая будет достигнута, когда анимация будет завершена. Непонятная часть возникает, когда я пытаюсь установить KeyTime — когда именно ключевой кадр будет активирован. Вы видите огромное значение, которое я устанавливаю через интервал времени: 5000000 .
Это не ошибка. Фактически, это показывает, как WinRT TimeSpan отличается от того, что вы использовали ранее. И это относится к C ++ / Cx и JavaScript, используемым для приложений Windows 8. Существует только одно поле, которое вы можете изменить — Продолжительность. И в отличие от значений, которые вы использовали для стандартного .NET TimeSpan, в этом случае используются единицы измерения по 100 наносекунд.
5000000 — это 5000000 * 100 наносекунд. Это дает нам 0,5 секунды. Здесь вам придется немного разобраться с базовой алгеброй, особенно с большими кусками анимации, выполненными в коде.
Когда я настраиваю все для экземпляра LinearDoubleKeyFrame, я добавляю его в свой базовый экземпляр DoubleAnimationUsingKeyFrames. То же относится и к любому другому типу ключевого кадра. И последнее, но не менее важное: не забудьте добавить контейнер ключевого кадра кода в экземпляр Storyboard:
yourStoryboard->Children->Append(doubleAnimation);
Всякий раз, когда вы хотите запустить анимацию, просто используйте yourStoryboard-> Begin ();