Анимации по ключевым кадрам в WinRT

78

Во всех программах, рассмотренных ранее, свойства анимировались от одного значения до другого - обычно задаваемых свойствами From и To классов DoubleAnimation, ColorAnimation и PointAnimation, а все разнообразие сводилось только к нелинейности перехода от From к To и инверсии анимации от To к From.

А если потребуется анимировать свойство от одного значения к другому, а затем к третьему... и даже далее? Решение, которое первым приходит в голову - определение в Storyboard нескольких анимаций с одним целевым свойством и использованием BeginTime для задержки некоторых анимаций, чтобы они не перекрывались. Однако это невозможно - объект Storyboard может содержать не более одной анимации, работающей с конкретным свойством.

Правильным решением будет анимация по ключевым кадрам (key frame animation), ход которой определяется серией ключевых кадров. Каждый ключевой кадр определяет значение свойства по прошествии заданного отрезка времени, а также способ перехода от предыдущего значения ключевого кадра к новому. Современные приложения, наподобие skype для windows 7, интенсивно используют анимацию по ключевым кадрам, для создания удобного графического интерфейса пользователя.

Ниже приведен простой пример анимации по ключевым кадрам, применяемой к свойству Center объекта EllipseGeometry для перемещения круга по экрану:

<Page ...>

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Path Fill="LimeGreen">
            <Path.Data>
                <EllipseGeometry x:Name="ell" RadiusX="18" RadiusY="18" />
            </Path.Data>
        </Path>
    </Grid>

    <Page.Triggers>
        <EventTrigger>
            <BeginStoryboard>
                <Storyboard>
                    <PointAnimationUsingKeyFrames Storyboard.TargetName="ellipse"
                                                  RepeatBehavior="Forever"
                                                  Storyboard.TargetProperty="Center"
                                                  EnableDependentAnimation="True"
                                                  >
                        <DiscretePointKeyFrame KeyTime="0:0:0" Value="100 100" />
                        <LinearPointKeyFrame KeyTime="0:0:1.9" Value="700 700" />
                        <LinearPointKeyFrame KeyTime="0:0:2" Value="700 100" />
                        <LinearPointKeyFrame KeyTime="0:0:3.9" Value="100 700" />
                        <LinearPointKeyFrame KeyTime="0:0:4" Value="100 100" />
                    </PointAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Page.Triggers>

</Page>

На рисунке ниже показана позиция анимированного шарика:

Использование ключевых кадров для анимации

Вместо PointAnimation в тег Storyboard включается тег PointAnimationUsingKeyFrames. Вместо задания свойств From, To и Duration в PointAnimation, тег PointAnimationUsingKeyFrames содержит потомков типа DiscretePointKeyFrame и LinearPointKeyFrame.

Каждый ключевой кадр в коллекции определяет, каким должно быть значение целевого свойства в заданный момент времени от начала анимации. Очень часто коллекция ключевых кадров начинается с элемента Discrete, инициализируемого нулевым значением KeyTime:

<DiscretePointKeyFrame KeyTime="0:0:0" Value="100 100" />

Следующий ключевой кадр в коллекции выглядит так:

<LinearPointKeyFrame KeyTime="0:0:1.9" Value="700 700" />

Это определение означает, что целевое свойство линейно возрастает от предыдущей точки (100, 100) до точки (700, 700) за две секунды. Итак, через две секунды свойство принимает значение (700, 700).

Следующий ключевой кадр существенно ускоряет темп анимации:

<LinearPointKeyFrame KeyTime="0:0:2" Value="700 100" />

За время, проходящее от 1,9 секунды до 2 секунд, точка (700,700) переходит в точку (700,100). Затем анимация снова замедляется на следующие две секунды. Остается последний ключевой кадр. Через 4 секунды значение целевого свойства достигает (100, 100), а анимация завершается. В этот момент она может пойти в обратном направлении (если свойство AutoReverse равно true) или начаться заново (если задано соответствующее значение RepeatBehavior).

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

Для хранения коллекции ключевых кадров класс PointAnimationUsinggKeyFrames определяет свойство KeyFrames типа PointKeyFrameCollection, которое представляет собой коллекцию объектов PointKeyFrame.

PointKeyFrame определяет свойства KeyTime и Value. У PointKeyFrame существуют четыре производных класса, причем два из них мы уже видели:

DiscretePointKeyFrame

Переходит к конкретному значению.

LinearPointKeyFrame

Выполняет линейную анимацию.

SplinePointKeyFrame

Ускоряет или замедляет анимацию.

EasingPointKeyFrame

Выполняет анимацию с функцией плавной анимации.

Также в Windows Runtime включен класс DoubleAnimationUsingKeyFrames с коллекцией объектов DoubleKeyFrame, имеющими аналогичные производные классы Discrete, Linear, Spline и Easing, и класс ColorAnimationUsingKeyFrames с коллекцией объектов типа ColorKeyFrame, имеющих аналогичные производные классы Discrete, Linear, Spline и Easing.

В следующем проекте класс ColorAnimationUsingKeyFrames используется для окрашивания фона панели в цвета, анимируемые по радужному спектру:

<Page ...>

    <Grid>
        <Grid.Background>
            <SolidColorBrush x:Name="brush" />
        </Grid.Background>
    </Grid>

    <Page.Triggers>
        <EventTrigger>
            <BeginStoryboard>
                <Storyboard RepeatBehavior="Forever">
                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="brush"
                                                  Storyboard.TargetProperty="Color">
                        <DiscreteColorKeyFrame KeyTime="0:0:0" Value="Red" />
                        <LinearColorKeyFrame KeyTime="0:0:1" Value="Yellow" />
                        <LinearColorKeyFrame KeyTime="0:0:2" Value="Green" />
                        <LinearColorKeyFrame KeyTime="0:0:3" Value="LightBlue" />
                        <LinearColorKeyFrame KeyTime="0:0:4" Value="Blue" />
                        <LinearColorKeyFrame KeyTime="0:0:5" Value="Purple" />
                        <LinearColorKeyFrame KeyTime="0:0:6" Value="Red" />
                    </ColorAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Page.Triggers>

</Page>

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

Объекты SplineDoubleKeyFrame, SplineColorKeyFrame и SplinePointKeyFrame сейчас используются реже, чем прежде, потому что большая часть их функциональности была заменена функциональностью EasingDoubleKeyFrame, EasingColorKeyFrame и EasingPointKeyFrame. В Spline-разновидностях объект KeySpline используется для определения двух контрольных точек кривой Безье, которая начинается в точке (0,0) и завершается в точке (1, 1). Кривая играет ту же роль, что и функция плавной анимации: она изменяет темп анимации, заставляя ее ускоряться и замедляться.

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