Общие сведения об анимации по ключевым кадрам

Обновлен: Ноябрь 2007

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

В этом разделе содержатся следующие подразделы.

  • Обязательные условия

  • Использование анимации по полным кадрам

  • См. также

Обязательные условия

Чтобы понять лучше этот руководство, необходимо ознакомиться с анимацией Windows Presentation Foundation (WPF) и шкалами времени. Введение в анимацию см. в разделе Общие сведения об эффектах анимации. Там же можно ознакомиться с анимацией From/To/By. Дополнительные сведения см. в разделе Общие сведения об анимациях From/To/By.

Что такое анимация по полным кадрам?

Подобно анимации From/To/By, анимация по полным кадрам анимирует значение заданного свойства. Она создает переход между заданными значениями во время его Duration. Однако если анимация From/To/By создает переход между двумя значениями, то анимация по полным кадрам может создавать переходы между любым числом целевых значений. В отличие от анимации From/To/By, анимация по полным кадрам не содержит свойств From,To или By, с которыми требуется задать ее заданные значения. Анимация по полным кадрам задает значения, которые описаны с помощью объектов полных кадров (поэтому и используется термин «анимация по полным кадрам»). Чтобы задать целевые значения анимации, создайте объекты полных кадров и добавьте их в коллекцию элементов анимации KeyFrames. При запуске анимации она выполняет переход между указанными кадрами.

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

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

  • Объявите анимацию и задайте ее Duration, так же как для анимации from/to/by.

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

  • Свяжите анимацию со свойством так же, как в анимации From/To/By. Дополнительные сведения о применении анимации к свойству с помощью раскадровки см. в разделе Общие сведения о Storyboard.

В следующем примере DoubleAnimationUsingKeyFrames используется для анимации элемента Rectangle в четырех разных местах.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- 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">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

Подобно анимации From/To/By, анимация по полным кадрам может применяться к свойству с помощью Storyboard в разметке и коде или с помощью метода BeginAnimation в коде. Также можно использовать анимацию по полным кадрам, чтобы создать AnimationClock и применить его к одному или нескольким свойствам. Дополнительные сведения о различных методах применения анимации см. в разделе Общие сведения о методах анимации свойств.

Типы анимации по полным кадрам

Поскольку анимация создает значения свойств, для различных типов свойств существуют различные типы анимации. Для анимации свойства, которое принимает Double (как, например, свойство Width элемента), используйте анимацию, создающую значения Double. Для анимации свойства, которое принимает Point, используйте анимацию, создающую значения Point и т. д.

Классы анимации по полным кадрам принадлежат к пространству имен System.Windows.Media.Animation и соответствуют следующему соглашению об именах:

*<Тип>*AnimationUsingKeyFrames

Где <Тип> является типом значения, анимируемого классом.

WPF предоставляет следующие классы анимации по полным кадрам.

Тип свойства

Соответствующий класс анимации from/to/by

Поддерживаемые методы интерполяции

Boolean

BooleanAnimationUsingKeyFrames

Дискретный

Byte

ByteAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Color

ColorAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Decimal

DecimalAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Double

DoubleAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Int16

Int16AnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Int32

Int32AnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Int64

Int64AnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Matrix

MatrixAnimationUsingKeyFrames

Дискретный

Object

ObjectAnimationUsingKeyFrames

Дискретный

Point

PointAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Quaternion

QuaternionAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Rect

RectAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Rotation3D

Rotation3DAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Single

SingleAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

String

StringAnimationUsingKeyFrames

Дискретный

Size

SizeAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Thickness

ThicknessAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Vector3D

Vector3DAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Vector

VectorAnimationUsingKeyFrames

Дискретный, линейный, сплайновый

Заданные значения (полные кадры) и время полных кадров

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

*<InterpolationMethod><Тип>*KeyFrame

Где <InterpolationMethod> — метод интерполяции, который использует полный кадр, а <Тип> — тип значения, которое класс анимирует. Анимация по полным кадрам, поддерживающая все три метода интерполяции, будет иметь три типа полных кадров, которые можно использовать. Например можно использовать три типа полных кадров с DoubleAnimationUsingKeyFrames: DiscreteDoubleKeyFrame, LinearDoubleKeyFrame и SplineDoubleKeyFrame. (Методы интерполяции описаны подробно в следующих разделах.)

Основной целью полного кадра является задание KeyTime и Value. Каждый тип полного кадра предоставляет эти два свойства.

  • Свойство Value указывает заданное значение для этого полного кадра.

  • Свойство KeyTime определяет, когда (в пределах анимации Duration) достигается значение полного кадра Value.

Когда начинается анимация по полным кадрам, итерация полных кадров происходит в порядке, определенном свойствами KeyTime.

  • Если в нулевой момент времени нет полного кадра, анимация создает переход между целевым значением свойства и Value первого полного кадра. В противном случае выходное значение анимации становится первым значением полного кадра.

  • Анимация создает переход между Value первого и второго полного кадра с помощью метода интерполяции, определяемого вторым полным кадром. Переход начинается с KeyTime первого полного кадра и заканчивается при достижении KeyTime второго полного кадра.

  • Анимация продолжается, при этом создаются переходы между каждым предыдущим и последующим полным кадром.

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

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

В следующем примере объект DoubleAnimationUsingKeyFrames, определенный в предыдущем примере, используется для демонстрации, как работают свойства Value и KeyTime.

  • Первый полный кадр немедленно устанавливает выходное значение анимации в 0.

  • Второй полный кадр анимируется от 0 до 350. Он запускается после окончания первого полного кадра (в момент времени равный 0 секунд), воспроизводится в течение 2 секунд и заканчивается в момент времени равный 0:0:2.

  • Третий полный кадр анимируется от 350 до 50. Он запускается после окончания второго полного кадра (в момент времени равный 2 секундам), воспроизводится в течение 5 секунд и заканчивается в момент времени равный 0:0:7.

  • Четвертый полный кадр анимируется от 50 до 200. Он запускается после окончания третьего полного кадра (в момент времени равный 7 секундам), воспроизводится в течение 1 секунды и заканчивается в момент времени равный 0:0:8.

  • Так как свойство Duration было установлено в значение 10 секунд, анимация хранит его конечное значение в течение двух секунд до времени окончания, равного 0:0:10.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="Microsoft.Samples.KeyFrameAnimations.KeyFramesIntroduction"
  WindowTitle="KeyFrame Animations">

  <Border Width="400" BorderBrush="Black">  

    <Rectangle Fill="Blue" 
      Width="50" Height="50"
      HorizontalAlignment="Left">
      <Rectangle.RenderTransform>
        <TranslateTransform 
          x:Name="MyAnimatedTranslateTransform" 
          X="0" Y="0" />
      </Rectangle.RenderTransform>
      <Rectangle.Triggers>
        <EventTrigger RoutedEvent="Rectangle.MouseLeftButtonDown">
          <BeginStoryboard>
            <Storyboard>

              <!-- 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">
                <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" />
                <LinearDoubleKeyFrame Value="350" KeyTime="0:0:2" />
                <LinearDoubleKeyFrame Value="50" KeyTime="0:0:7" />
                <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />                          
              </DoubleAnimationUsingKeyFrames>
            </Storyboard>
          </BeginStoryboard>
        </EventTrigger>
      </Rectangle.Triggers> 
    </Rectangle>
  </Border> 
</Page>

Методы интерполяции

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

Линейная интерполяция

При линейной интерполяции длительность сегментов при анимации остается постоянной. Например, если сегмент полного кадра переходит от 0 до 10 в течение 5 секунд, анимация будет выводить следующие значения в указанное время:

Время

Выходное значение

0

0

1

2

2

4

3

6

4

8

4.25

8.5

4.5

9

5

10

Дискретная интерполяция

При дискретной интерполяции функция анимации переходит от одного значения к следующему без интерполяции. Если сегмент полного кадра переходит от 0 до 10 в течение 5 секунд, анимация будет выводить следующие значения в указанное время:

Время

Выходное значение

0

0

1

0

2

0

3

0

4

0

4.25

0

4.5

0

5

10

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

Сплайновая интерполяция является более сложной. Оно описана в следующем разделе.

Сплайновая интерполяция

Сплайновую интерполяцию можно использовать для достижения более реалистичных временных эффектов. Поскольку анимация часто используются для имитации эффектов, которые возникают в реальных условиях, разработчикам может потребоваться тонкое управление ускорением и замедлением объектов и сегментами времени. Полные сплайновые кадры позволяют создавать анимацию с помощью сплайновой интерполяции. Вместе с другими полными кадрами определяются Value и KeyTime. С полным сплайновым кадром также указывается KeySpline. В следующем примере показан один сплайновый полный кадр для DoubleAnimationUsingKeyFrames. Обратите внимание на свойство KeySpline; именно этим сплайновый полный кадр отличается от других типов полных кадров.

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

Кривая Безье третьего порядка определяется начальной точкой, конечной точкой и двумя контрольными точками. Свойство KeySpline сплайнового полного кадра определяет две контрольные точки кривой Безье на участке от (0,0) до (1,1). Первая контрольная точка управляет коэффициентом кривизны первой половины кривой Безье, а вторая — коэффициентом кривизны второй половины сегмента Безье. Полученная кривая описывает частоту изменения для этого сплайнового полного кадра. Чем круче кривая, тем быстрее полный кадр изменяет свои значения. Чем более плоской становится кривая, тем медленнее изменяет свои значения полный кадр.

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

В следующем примере для KeySpline задается значение 0,1 1,0, которое создает следующую кривую Безье.

Ключевой сплайн с контрольными точками (0,0, 1,0) и (1,0, 0,0)
Кривая Безье

<SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

Этот полный кадр анимируется быстро при запуске, замедляется и затем снова ускоряется перед завершением.

В следующем примере для KeySpline задается значение 0,5, 0,25 0,75, 1,0, которое создает следующую кривую Безье.

Ключевой сплайн с контрольными точками (0,25, 0,5) и (0,75, 1,0)
Кривая Безье

<SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />

Поскольку изгиб кривой Безье изменяется незначительно, этот полный кадр анимируется почти с постоянной скоростью; он несколько замедляется перед завершением.

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

<!-- This rectangle is animated using a key frame animation
     with splined interpolation. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Purple">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="SplineAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="SplineAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">                
            <SplineDoubleKeyFrame Value="500" KeyTime="0:0:7" KeySpline="0.0,1.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="200" KeyTime="0:0:10"  KeySpline="0.0,0.0 1.0,0.0" />

            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  KeySpline="0.25,0.5 0.75,1" />
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

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

Объединение методов интерполяции

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

В следующем примере создается DoubleAnimationUsingKeyFrames, который использует линейную, сплайновую и дискретную интерполяцию.

<!-- This rectangle is animated using a key frame animation
     with a combination of interpolation methods. -->
<Rectangle 
  Width="50"
  Height="50"
  Fill="Orange">  
  <Rectangle.RenderTransform>
    <TranslateTransform 
      x:Name="ComboAnimatedTranslateTransform" 
      X="0" Y="0" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>

          <!-- Animate the TranslateTransform's X property
               from its base value (0) to 500, then 200,
               then 350 over 15 seconds. -->
          <DoubleAnimationUsingKeyFrames
            Storyboard.TargetName="ComboAnimatedTranslateTransform"
            Storyboard.TargetProperty="X"
            Duration="0:0:15"
            RepeatBehavior="Forever">
            <DiscreteDoubleKeyFrame Value="500" KeyTime="0:0:7" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:10" />
            <SplineDoubleKeyFrame Value="350" KeyTime="0:0:15"  
              KeySpline="0.25,0.5 0.75,1" />                      
          </DoubleAnimationUsingKeyFrames>           
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers> 
</Rectangle>

Дополнительные сведения о длительности и времени полного кадра

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

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

В следующем списке описываются различные способы определения времени полного кадра.

Значения TimeSpan

Можно использовать значение TimeSpan для указания KeyTime. Значение должно быть больше или равно 0 и меньше или равно длительности анимации. В следующем примере показана анимация с длительностью 10 секунд и четыре полных кадра, время которых указывается в виде значения времени.

  • Первый полный кадр анимируется от базового значения до 100 в первые 3 секунды и заканчивается в момент времени равный 0:0:03.

  • Второй полный кадр анимируется от 100 до 200. Он запускается после окончания первого полного кадра (в момент времени равный 3 секундам), воспроизводится в течение 5 секунд, и заканчивается в момент времени равный 0:0:8.

  • Третий полный кадр анимируется от 200 до 500. Он запускается после окончания второго полного кадра (в момент времени равный 8 секундам), воспроизводится в течение 1 секунды и заканчивается в момент времени равный 0:0:9.

  • Четвертый полный кадр анимируется от 500 до 600. Он запускается после окончания третьего полного кадра (в момент времени равный 9 секундам), воспроизводится в течение 1 секунды и заканчивается в момент времени равный 0:0:10.

<!-- This rectangle is animated with KeyTimes using TimeSpan values. 
     Goes to 100 in the first 3 seconds, 100 to 200 in 
     the next 5 seconds, 300 to 500 in the next second,
     and 500 to 600 in the final second. -->
<Rectangle Width="50" Height="50" Fill="Blue">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform01" X="10" Y="30" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform01" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as TimeSpan values 
                 which are in the form of "hours:minutes:seconds". -->
            <LinearDoubleKeyFrame Value="100" KeyTime="0:0:3" />
            <LinearDoubleKeyFrame Value="200" KeyTime="0:0:8" />
            <LinearDoubleKeyFrame Value="500" KeyTime="0:0:9" />
            <LinearDoubleKeyFrame Value="600" KeyTime="0:0:10" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Значения в процентах

Процентное значение указывает, что полный кадр заканчивается по истечении некоторого процента от Duration анимации. В XAML задайте процент в виде числа за которым следует символ %. В коде используйте метод FromPercent и передайте его Double, указав процент. Значение должно быть больше или равно 0 и меньше или равно 100%. В следующем примере показана анимация длительностью 10 секунд и четыре полных кадра, время которых указывается в виде процентов.

  • Первый полный кадр анимируется от базового значения до 100 в первые 3 секунды и заканчивается в момент времени равный 0:0:3.

  • Второй полный кадр анимируется от 100 до 200. Он запускается после окончания первого полного кадра (в момент времени равный 3 секундам), воспроизводится в течение 5 секунд, и заканчивается в момент времени равный 0:0:8 (0,8 * 10 = 8).

  • Третий полный кадр анимируется от 200 до 500. Он запускается после окончания второго полного кадра (в момент времени равный 8 секундам), воспроизводится в течение 1 секунды и заканчивается в момент времени равный 0:0:9 (0.9 * 10 = 9).

  • Четвертый полный кадр анимируется от 500 до 600. Он запускается после окончания третьего полного кадра (в момент времени равный 9 секундам), воспроизводится в течение 1 секунды и заканчивается в момент времени равный 0:0:10 (1 * 10 = 10).

<!-- Identical animation behavior to the previous rectangle 
     but using percentage values for KeyTimes rather then TimeSpan. -->
<Rectangle Height="50" Width="50" Fill="Purple">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform02" X="10" Y="110" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform02" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed as Percentages. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="30%" />
            <LinearDoubleKeyFrame Value="200" KeyTime="80%" />
            <LinearDoubleKeyFrame Value="500" KeyTime="90%" />
            <LinearDoubleKeyFrame Value="600" KeyTime="100%" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Специальные значения, унифицирование

Используйте расчет времени Uniform, если необходимо, чтобы каждый полный кадр продолжался одно и то же количество времени.

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

  • Первый полный кадр анимируется от базового значения до 100 в первые 2,5 секунды и заканчивается в момент времени равный 0:0:2.5.

  • Второй полный кадр анимируется от 100 до 200. Он запускается после окончания первого полного кадра (в момент времени = 2,5 секунд), воспроизводится примерно в течение 2,5 секунды и заканчивается в момент времени равный 0:0:5.

  • Третий полный кадр анимируется от 200 до 500. Он запускается после окончания второго полного кадра (в момент времени равный 5 секундам), воспроизводится в течение 2,5 секунды и заканчивается в момент времени равный 0:0:7.5.

  • Четвертый полный кадр анимируется от 500 до 600. Он запускается после окончания второго полного кадра (в момент времени равный 7,5 секунды), воспроизводится в течение 2,5 секунды и заканчивается в момент времени равный 0:0:1.

<!-- This rectangle is animated with KeyTimes using Uniform values.  -->
<Rectangle Height="50" Width="50" Fill="Red">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform03" X="10" Y="190" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform03" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Uniform. 
                 When a key time is set to "Uniform" the total allotted 
                 time of the animation is divided evenly between key frames.  
                 In this example, the total duration of the animation is 
                 ten seconds and there are four key frames each of which 
                 are set to "Uniform", therefore, the duration of each key frame 
                 is 3.3 seconds (10/3). -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Uniform" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Uniform" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Специальные значения, скорость

Используйте расчет времени Paced, если требуется анимация с постоянной скоростью.

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

<!-- Using Paced Values. Rectangle moves between key frames at 
     uniform rate except for first key frame
     because using a Paced value on the first KeyFrame in a 
     collection of frames gives a time of zero. -->
<Rectangle Height="50" Width="50" Fill="Orange">
  <Rectangle.RenderTransform>
    <TranslateTransform x:Name="TranslateTransform04" X="10" Y="270" />
  </Rectangle.RenderTransform>
  <Rectangle.Triggers>
    <EventTrigger RoutedEvent="Rectangle.Loaded">
      <BeginStoryboard>
        <Storyboard>
          <DoubleAnimationUsingKeyFrames 
            Storyboard.TargetName="TranslateTransform04" 
            Storyboard.TargetProperty="X"
            Duration="0:0:10"
            RepeatBehavior="Forever">

            <!-- KeyTime properties are expressed with values of Paced. 
                 Paced values are used when a constant rate is desired. 
                 The time allocated to a key frame with a KeyTime of "Paced" 
                 is determined by the time allocated to the other key 
                 frames of the animation. This time is calculated to 
                 attempt to give a "paced" or "constant velocity" 
                 for the animation. -->
            <LinearDoubleKeyFrame Value="100" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="200" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="500" KeyTime="Paced" />
            <LinearDoubleKeyFrame Value="600" KeyTime="Paced" />
          </DoubleAnimationUsingKeyFrames>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Rectangle.Triggers>
</Rectangle>

Обратите внимание, что если временем последнего полного кадра является Paced или Uniform, его определяемое время будет установлено в 100 процентов. Если первый полный кадр в мультикадровой анимации является процентным, его полное время будет равным 0. (Если коллекция полных кадров содержит только один кадр и это процентный полный кадр, его полное время будет установлено в 100 процентов).

Различные полные кадры в пределах одной анимации по полным кадрам могут использовать различные типы полного времени.

Объединение типов полного времени, поврежденные полные кадры

Можно использовать полные кадры с различными типами значений KeyTime в одной анимации. Хотя рекомендуется добавлять полные кадры в том порядке, в котором они должны воспроизводиться, это не является необходимым. Анимация и система расчета времени способны определить порядок полных кадров. Полные кадры с недопустимым полным временем игнорируются.

В следующем списке описывается процедура, по которой полное время определяется для полного кадра анимации по полным кадрам.

  1. Определите значения TimeSpan KeyTime.

  2. Определите общее время интерполяции анимации, то есть общее время, затрачиваемое на анимацию по полным кадрам на выполнение прямой итерации.

    1. Если Duration анимации не является Automatic или Forever, общим временем интерполяции является значение свойства Duration анимации.

    2. В противном случае временем интерполяции будет являться наибольшее значение TimeSpan KeyTime, которое указано полными кадрами (если таковое имеется).

    3. Если нет — общим временем интерполяции будет являться 1 секунда.

  3. Используйте значение общего времени интерполяции для определения значений Percent KeyTime.

  4. Определите последний полный кадр, если он не был еще определен на предыдущих этапах. Если KeyTime последнего полного кадра является Uniform или Paced, его определенное время будет совпадать с общим временем интерполяции.

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

  5. Определите оставшиеся значения Uniform KeyTime: каждое из них получает равную долю доступного времени. В ходе этого процесса неопределенные значения Paced KeyTime временно рассматриваются как значения Uniform KeyTime и получают временно определенное время.

  6. Определите значение KeyTime для полных кадров с неопределенным полным временем с помощью полных кадров, объявленных рядом с ними, которые имеют определенные значения KeyTime.

  7. Определите оставшиеся значения Paced KeyTime. Paced KeyTime используют значения KeyTime соседних полных кадров, чтобы определить их определенное время. Это необходимо, убедиться в том, что скорость анимации является постоянной во время этих полных кадров.

  8. Отсортируйте полные кадры в порядке определенного времени (первичный ключ), и в порядке объявления (вторичный ключ), то есть используйте строгую сортировку на основе определенных значений KeyTime полных кадров.

См. также

Задачи

Пример использования анимации ключевого сплайна

Пример анимации с ключевыми кадрами

Основные понятия

Общие сведения об эффектах анимации

Общие сведения о Storyboard

Общие сведения о характере поведения во времени

Ссылки

KeyTime

KeySpline

Timeline

Другие ресурсы

Практические руководства, посвященные анимации по полным кадрам