Поделиться через


Анимации с ключевым кадром и анимации с упрощенной функцией

Линейные анимации ключевых кадров, анимации ключевых кадров с значением KeySpline или функции упрощения — это три различных метода примерно для одного сценария: создание раскадровной анимации, которая немного сложнее, и которая использует нелинейное поведение анимации от начального состояния до конечного состояния.

Необходимые компоненты

Убедитесь, что вы прочитали раздел раскадровки анимаций . Этот раздел основан на концепциях анимации, которые были описаны в раскадровки анимации и не будут повторяться. Например, раскадровка анимации описывает, как нацеливать анимацию, раскадровки как ресурсы, значения свойств временной шкалы, такие как Duration, FillBehavior и т. д.

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

Анимации с ключевым кадром позволяют достичь нескольких целевых значений, которые достигаются в точке вдоль временной шкалы анимации. Другими словами, каждый ключевой кадр может указать другое промежуточное значение, а последний ключевой кадр достигается окончательным значением анимации. Указав несколько значений для анимации, можно сделать более сложные анимации. Анимации с ключевым кадром также позволяют реализовать различные логики интерполяции, которые реализуются в качестве отдельного подкласса keyFrame для каждого типа анимации. В частности, каждый тип анимации с ключевым кадром имеет дискретный, линейный, spline и упрощенный вариант класса keyFrame для указания ключевых кадров. Например, чтобы указать анимацию, предназначенную для двойного и использующего ключевые кадры, можно объявить ключевые кадры с Дискретными кадрамиKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame и EasingDoubleKeyFrame. Вы можете использовать любые и все эти типы в одной коллекции ключевых кадров , чтобы изменить интерполяцию при каждом достижении нового ключевого кадра.

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

В начале анимации, если ключевой кадр с keyTime "0:0:0" существует, начальное значение независимо от неинимированного значения свойства. Это похоже на то, как анимация from//By действует, если нет от.

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

Помимо длительности, можно задать все свойства временной шкалы на основе анимации ключевых кадров, например анимацию from//By, так как классы анимации ключевых кадров также являются производными от временной шкалы. К ним относятся:

  • AutoReverse: после достижения последнего ключевого кадра кадры повторяются в обратном порядке с конца. Это удвоит очевидную длительность анимации.
  • BeginTime: задержка начала анимации. Временная шкала значений KeyTime в кадрах не начинает подсчет до тех пор, пока BeginTime не будет достигнута, поэтому нет риска отрезать кадры
  • FillBehavior: управляет тем, что происходит при достижении последнего ключевого кадра. FillBehavior не влияет на любые промежуточные ключевые кадры.
  • RepeatBehavior:
    • Если задано значение Forever, то ключевые кадры и их временная шкала повторяют бесконечно.
    • Если задано значение счетчика итерации, временная шкала повторяется несколько раз.
    • Если задано значение "Длительность", временная шкала повторяется до достижения этого времени. Это может усечь анимацию через последовательность ключевых кадров, если это не целый фактор неявной длительности временной шкалы.
  • SpeedRatio (часто не используется)

Линейные ключевые кадры

Линейные ключевые кадры приводят к простой линейной интерполяции значения до достижения keyTime кадра. Это поведение интерполяции наиболее похоже на более простые анимации from//By, описанные в разделе раскадровки анимаций.

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

<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimationUsingKeyFrames
              Storyboard.TargetName="myRectangle"
              Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                <LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:4"/>
                <LinearDoubleKeyFrame Value="2" KeyTime="0:0:5"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </StackPanel.Resources>
</StackPanel>

Дискретные ключевые кадры

Дискретные ключевые кадры вообще не используют интерполяцию. При достижении keyTime новое значение просто применяется. В зависимости от того, какое свойство пользовательского интерфейса анимируется, это часто создает анимацию, которая, как представляется, "переход". Будьте уверены, что это эстетическое поведение, которое вы действительно хотите. Вы можете свести к минимуму очевидные скачки, увеличив число ключевых кадров, которые вы объявляете, но если гладкая анимация является вашей целью, вы можете лучше использовать линейные или сплайн ключевые кадры.

Примечание.

Дискретные ключевые кадры — единственный способ анимации значения, которое не относится к типу Double, Point и Color, с дискретным кадромObjectKeyFrame. Далее мы обсудим это в этом разделе.

Ключевые кадры spline

Кадр ключа spline создает переменный переход между значениями в соответствии со значением свойства KeySpline . Это свойство задает первые и второй контрольные точки кривой Bezier, описывающие ускорение анимации. В основном, KeySpline определяет связь между функцией и временем, где граф времени функции является формой этой кривой Bezier. Обычно значение KeySpline указывается в строке атрибута XAML с четырьмя двойными значениями, разделенными пробелами или запятыми. Эти значения являются парами "X,Y" для двух контрольных точек кривой Bezier. "X" — это время, а "Y" — это модификатор функции для значения. Каждое значение всегда должно быть от 0 до 1 включительно. Без изменения точки управления в KeySpline прямая линия от 000 до 1,1 является представлением функции с течением времени для линейной интерполяции. Точки управления изменяют форму этой кривой и таким образом поведение функции с течением времени для анимации сплайна. Это, вероятно, лучше всего увидеть это визуально как граф. Вы можете запустить пример визуализатора с помощью клавиш Silverlight в браузере, чтобы узнать, как точки управления изменяют кривую и как пример анимации выполняется при использовании в качестве значения KeySpline .

В следующем примере показаны три разных ключевых кадра, примененных к анимации, а последний — анимация с строкой ключа для двойного значения (SplineDoubleKeyFrame). Обратите внимание на строку "0.6,0.0 0.9,0.00", примененную для KeySpline. Это создает кривую, в которой анимация, как представляется, выполняется медленно, но затем быстро достигает значения непосредственно до достижения KeyTime .

<Storyboard x:Name="myStoryboard">
    <!-- Animate the TranslateTransform's X property
        from 0 to 350, then 50,
        then 200 over 10 seconds. -->
    <DoubleAnimationUsingKeyFrames
        Storyboard.TargetName="MyAnimatedTranslateTransform"
        Storyboard.TargetProperty="X"
        Duration="0:0:10" EnableDependentAnimation="True">

        <!-- Using a LinearDoubleKeyFrame, the rectangle moves 
            steadily from its starting position to 500 over 
            the first 3 seconds.  -->
        <LinearDoubleKeyFrame Value="500" KeyTime="0:0:3"/>

        <!-- Using a DiscreteDoubleKeyFrame, the rectangle suddenly 
            appears at 400 after the fourth second of the animation. -->
        <DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4"/>

        <!-- Using a SplineDoubleKeyFrame, the rectangle moves 
            back to its starting point. The
            animation starts out slowly at first and then speeds up. 
            This KeyFrame ends after the 6th second. -->
        <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:6"/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Упрощение ключевых кадров

Ключевой кадр упрощения — это ключевой кадр, в котором применяется интерполяция, а функция с течением времени интерполяции управляется несколькими предварительно определенными математическими формулами. На самом деле вы можете создать гораздо тот же результат с помощью ключевого кадра сплайна, что и с некоторыми типами функций упрощения, но есть и некоторые функции упрощения, такие как BackEase, которые нельзя воспроизвести с помощью сплайна.

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

В этом примере применяется КубическаяEase, а затем bounceEase в качестве последовательных ключевых кадров к DoubleAnimation, чтобы создать эффект отскоки.

<Storyboard x:Name="myStoryboard">
    <DoubleAnimationUsingKeyFrames Duration="0:0:10"
        Storyboard.TargetProperty="Height"
        Storyboard.TargetName="myEllipse">

        <!-- This keyframe animates the ellipse up to the crest 
            where it slows down and stops. -->
        <EasingDoubleKeyFrame Value="-300" KeyTime="00:00:02">
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>

        <!-- This keyframe animates the ellipse back down and makes
            it bounce. -->
        <EasingDoubleKeyFrame Value="0" KeyTime="00:00:06">
            <EasingDoubleKeyFrame.EasingFunction>
                <BounceEase Bounces="5"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Это только один пример функции упрощения. Дополнительные сведения см. в следующем разделе.

Функции для реалистичной анимации

Функции плавности позволяют применять к анимациям настраиваемые математические формулы. Математические операции часто полезны для создания анимаций, которые имитируют реальную физику в 2-D-системе координат. Например, требуется реалистичный отскок объекта или его поведение так, словно он подвешен на пружине. Вы можете использовать ключевые кадры или даже анимации from//By для приближения этих эффектов, но это займет значительное количество работы, и анимация будет менее точной, чем с помощью математической формулы.

Функции упрощения можно применять к анимациям тремя способами:

Ниже приведен список функций упрощения.

  • BackEase: удаляет движение анимации немного, прежде чем он начинает анимироваться в указанном пути.
  • BounceEase: создает эффект отскоки.
  • CircleEase: создает анимацию, которая ускоряет или уменьшается с помощью циклической функции.
  • CubeEase: создает анимацию, которая ускоряет или уменьшается с помощью формулы f(t) = t3.
  • ElasticEase: создает анимацию, которая напоминает весеннюю колебания назад и вперед, пока она не придет к отдыху.
  • ЭкспоненциальнаяEase: создает анимацию, которая ускоряет или уменьшается с помощью экспоненциальной формулы.
  • PowerEase: создает анимацию, которая ускоряет или уменьшается с помощью формулы f(t) = tp, где p равно свойству Power.
  • QuadraticEase: создает анимацию, которая ускоряет или уменьшается с помощью формулы f(t) = t2.
  • QuarticEase: создает анимацию, которая ускоряет или уменьшается с помощью формулы f(t) = t4.
  • QuinticEase: создание анимации, которая ускоряет или уменьшается с помощью формулы f(t) = t5.
  • SineEase: создает анимацию, которая ускоряет или уменьшается с помощью синусовой формулы.

Некоторые функции упрощения имеют собственные свойства. Например, BounceEase имеет два свойства Bounces и Bounciness, которые изменяют поведение функции с течением времени этого конкретного bounceEase. Другие функции упрощения, такие как CubicEase, не имеют свойств, отличных от свойства EasingMode, которые совместно используют все функции, и всегда создают одно и то же поведение с течением времени.

Некоторые из этих функций упрощения имеют немного перекрытия в зависимости от того, как вы задаете свойства для функций с упрощением, имеющими свойства. Например, QuadraticEase точно совпадает с PowerEase с PowerEase равным 2. И CircleEase в основном является экспоненциальным экспоненциальным значением по умолчанию.

Функция упрощения BackEase уникальна, так как она может изменить значение вне обычного диапазона, заданное параметром From/To или значениями ключевых кадров. Она запускает анимацию, изменяя значение в противоположном направлении, как ожидалось от обычного поведения from/To, возвращается к значению from или запуска снова, а затем запускает анимацию как обычное.

В предыдущем примере мы показали, как объявить функцию упрощения для анимации ключевых кадров. Следующий пример применяет функцию упрощения к анимации from/To/By.

<StackPanel x:Name="LayoutRoot" Background="White">
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <DoubleAnimation.EasingFunction>
                    <BounceEase Bounces="2" EasingMode="EaseOut" 
                                Bounciness="2"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </StackPanel.Resources>
    <Rectangle x:Name="myRectangle" Fill="Blue" Width="200" Height="30"/>
</StackPanel>

Когда функция упрощения применяется к анимации from//To By, она изменяет характеристики функции с течением времени о том, как значение интерполяется между значениями from и To в течение длительности анимации. Без функции упрощения это будет линейная интерполяция.

Анимации дискретных значений объектов

Один из типов анимации заслуживает особого упоминания, потому что это единственный способ применения анимированного значения к свойствам, которые не относятся к типа Double, Point или Color. Это анимация key-frame ObjectAnimationUsingKeyFrames. Анимация с помощью значений объектов отличается, так как нет возможности интерполяции значений между кадрами. После достижения keyTime кадра анимированное значение немедленно устанавливается в значение, указанное в значении ключевого кадра. Так как интерполяция отсутствует, в коллекции ключевых кадров ObjectAnimationUsingKeyFrames используется только один ключевой кадр: DiscreteObjectKeyFrame.

Значение Дискретного ОбъектаKeyFrame часто задается с помощью синтаксиса элемента свойства, так как значение объекта, которое вы пытаетесь задать, часто не является выражением строки для заполнения значения в синтаксисе атрибута. Если вы используете ссылку, например StaticResource, можно использовать синтаксис атрибутов.

В одном месте вы увидите объект ObjectAnimationUsingKeyFrames, используемый в шаблонах по умолчанию, когда свойство шаблона ссылается на ресурс Кисти. Эти ресурсы являются объектами SolidColorBrush, а не только значением color, и они используют ресурсы, определенные как системные темы (ThemeDictionaries). Они могут быть назначены непосредственно значению типа кисти, например TextBlock.Foreground , и не нужно использовать непрямую целевую ориентацию. Но поскольку SolidColorBrush не является двойным, point или Color, необходимо использовать ObjectAnimationUsingKeyFrames для использования ресурса.

<Style x:Key="TextButtonStyle" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <TextBlock x:Name="Text"
                        Text="{TemplateBinding Content}"/>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
...
                       </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Можно также использовать ObjectAnimationUsingKeyFrames для анимации свойств, использующих значение перечисления. Ниже приведен еще один пример именованного стиля, который поставляется из шаблонов среда выполнения Windows по умолчанию. Обратите внимание, как оно задает свойство Видимости, которое принимает константу перечисления Видимости. В этом случае можно задать значение с помощью синтаксиса атрибутов. Для задания свойства со значением перечисления требуется только неквалифицированное имя константы, например "Свернутый".

<Style x:Key="BackButtonStyle" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Grid x:Name="RootGrid">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal"/>
...           <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame Value="Collapsed" KeyTime="0"/>
                  </ObjectAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
...
          </VisualStateManager.VisualStateGroups>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Для набора кадров ObjectAnimationUsingKeyFrame можно использовать несколько дискретных ОбъектовObjectKeyFrames. Это может быть интересным способом создания анимации "слайд-шоу", анимируя значение Image.Source, в качестве примера сценария, в котором могут быть полезны несколько значений объектов.