Анимация ключевого кадра

68

Все виды анимации, которые были показаны до сих пор, используют линейную интерполяцию для перемещения из начальной точки в конечную. Но что, если понадобится создать анимацию, имеющую множество сегментов и движущуюся менее равномерно? Например, может понадобиться создать анимацию, сначала быстро задвигающую элементы в представление, а затем медленно перемещающую их в окончательные места. Такого эффекта можно достичь, создав последовательность двух анимаций и применив свойство BeginTime для запуска второй анимации по окончании первой. Однако существует более простой подход — использование анимации ключевого кадра.

Анимация ключевого кадра (key frame animation) — это анимация, состоящая из множества коротких сегментов. Каждый сегмент в анимации представляет начальное, конечное и промежуточное значения. После запуска анимация плавно переходит от одного значения к другому.

Например, рассмотрим анимацию Point, позволяющую перемещать центральную точку RadialGradientBrush из одного места в другое:

<PointAnimation Storyboard.TargetName="ellipse"
   Storyboard.TargetProperty="Fill.GradientOrigin"
   From="0.7,0.3" To="0.3,0.7" Duration="0:0:10" AutoReverse="True"
   RepeatBehavior="Forever">
</PointAnimation>

Этот объект PointAnimation может быть заменен эквивалентным PointAnimationUsingKeyFrames, как показано ниже:

<PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
   Storyboard.TargetProperty="Fill.GradientOrigin"
   AutoReverse="True" RepeatBehavior="Forever">
      <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:10"></LinearPointKeyFrame>
</PointAnimationUsingKeyFrames>

PointAnimationUsingKeyFrames выполняет линейную интерполяцию для плавного перемещения от первого кадра ко второму — так же, как это делает PointAnimation с установленными значениями From и То.

Каждый ключевой кадр использует собственный объект анимации (вроде LinearPointKeyFrame). По большей части эти классы одинаковы — они включают свойство Value, хранящее целевое значение, и свойство KeyTime, указывающее момент, когда кадр достигнет целевого значения. Единственное отличие связано с типом данных свойства Value. В LinearPointKeyFrame это Point, в DoubleKeyFrame — double и т.д.

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

<PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
   Storyboard.ТаrgetProperty="Fill.GradientOrigin"
   RepeatBehavior="Forever">
      <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></LinearPointKeyFrame>
      <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></LinearPointKeyFrame>
</PointAnimationUsingKeyFrames>

Эта анимация не является обратимой, но она повторяется. Чтобы исключить прыжки между финальным значением одной итерации и стартовым значением следующей, анимация завершается в той же точке, что и начинается.

Использование анимации ключевого кадра не обеспечивает такую же мощность, как последовательное применение множества анимаций. Наиболее существенное отличие в том, что к каждому ключевому кадру нельзя применять разные значения AccelerationRatio и DecelerationRatio — можно указать только одно значение для всей анимации в целом.

Дискретные анимации ключевого кадра

В анимации ключевого кадра, показанной в предыдущем примере, используются линейные ключевые кадры. В результате происходит гладкий переход между значениями ключевых кадров. Другим вариантом являются дискретные ключевые кадры. В их случае никакой интерполяции не выполняется. Когда наступает время очередного ключа, свойство мгновенно принимает новое значение.

Имена классов линейных ключевых кадров образуются в форме LinearТипДанныхKeyFrame. Имена классов дискретных ключевых кадров строятся в соответствии со схемой DiscreteТипДанныхKeyFrame. Рассмотрим измененную версию примера RadialGradientBrush, в которой используются дискретные ключевые кадры:

<PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
   Storyboard.ТаrgetProperty="Fill.GradientOrigin"
   RepeatBehavior="Forever">
      <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></DiscretePointKeyFrame>
      <DiscretePointKeyFrame Value="0.3,0.7" КеуТime="0:0:5"></DiscretePointKeyFrame>
      <DiscretePointKeyFrame Value="0.5,0.9" KeyTime="0:0:8"></DiscretePointKeyFrame>
      <DiscretePointKeyFrame Value="0.9,0.6" KeyTime="0:0:10"></DiscretePointKeyFrame>
      <DiscretePointKeyFrame Value="0.8,0.2" KeyTime="0:0:12"></DiscretePointKeyFrame>
      <DiscretePointKeyFrame Value="0.7,0.3" KeyTime="0:0:14"></DiscretePointKeyFrame>
</PointAnimationUsingKeyFrames>

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

Все классы анимации ключевого кадра поддерживают дискретные ключевые кадры, но только некоторые из них поддерживают линейные ключевые кадры. Все зависит от типа данных. Типы данных, поддерживающие линейные ключевые кадры — те же самые, что поддерживают и линейную интерполяцию, и они предоставляют класс TипДaнныxAnimation. Примеры включают Point, Color и double. Типы данных, не поддерживающие линейную интерполяцию, включают строки и объекты.

В одной и той же анимации ключевого кадра можно комбинировать оба типа ключевых кадров — линейные и дискретные.

Плавные ключевые кадры

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

Если это не то, что требуется, можно воспользоваться плавностью анимации для добавления ускорения и замедления к индивидуальным ключевым кадрам. Однако обычные линейные ключевые кадры и классы дискретных ключевых кадров не поддерживают этого средства. Взамен придется применять плавный ключевой кадр, такой как EasingDoubleKeyFrame, EasingColorKeyFrame и EasingPointKeyFrame. Каждый из них работает подобно своему линейному аналогу, но предоставляет дополнительное свойство EasingFunction.

Ниже приведен пример, в котором плавность анимации используется для применения эффекта ускорения к первым 5 секундам анимации ключевого кадра:

<PointAnimationUsingKeyFrames Storyboard.ТаrgеtName="ellipseBrush"
   Storyboard.TargetProperty= "GradientOrigin"
   RepeatBehavior="Forever">
     <LinearPointKeyFrame Value="0.7,0.3" KeyTime="0:0:0"></LinearPointKeyFrame>
     <EasingPointKeyFrame Value="0.3,0.7" KeyTime="0:0:5">
         <EasingPointKeyFrame.EasingFunction>
            <CircleEase></CircleEase>
         </EasingPointKeyFrame.EasingFunction>
     </EasingPointKeyFrame>
     ...
</PointAnimationUsingKeyFrames>

Комбинация ключевых кадров с функциями плавности анимации дает удобный способ моделирования сложных анимаций, но, возможно, еще не обеспечит нужную степень управления. Вместо использования функции плавности анимации можно создать математическую формулу, которая описывает ход анимации. Этот прием рассматривается в следующей статье.

Пройди тесты
Лучший чат для C# программистов