Partager via


Animations d’images clés et animations de fonction d’accélération

Les animations linéaires d’images clés, les animations de trame clé avec une valeur KeySpline ou les fonctions d’accélération sont trois techniques différentes pour un scénario assez similaire : pour créer une animation scénarisée un peu plus complexe qui utilise un comportement d’animation non linéaire depuis un état de départ jusqu'à un état final.

Prerequisites

Assurez-vous que vous avez lu la rubrique des animations scénarisées. Cette rubrique s’appuie sur les concepts d’animation qui ont été expliqués dans les animations storyboarded et ne les reprendra pas. Par exemple, les animations storyboarded décrivent comment cibler des animations, des storyboards en tant que ressources, les valeurs de propriété Timeline telles que Duration, FillBehavior, etc.

Animation à l’aide d’animations d’images clés

Les animations de trame clé permettent d’atteindre plusieurs valeurs cibles atteintes à un point le long de la chronologie d’animation. En d’autres termes, chaque image clé peut spécifier une valeur intermédiaire différente, et la dernière image clé atteinte est la valeur d’animation finale. En spécifiant plusieurs valeurs à animer, vous pouvez créer des animations plus complexes. Les animations de trame clé permettent également une logique d’interpolation différente, chacune implémentée en tant que sous-classe KeyFrame différente par type d’animation. Plus précisément, chaque type d’animation d’images clés a une variante Discrète, Linéaire, Spline et Adoucissement de sa classe KeyFrame pour spécifier ses images clés. Par exemple, pour spécifier une animation qui cible un double et utilise des images clés, vous pouvez déclarer des images clés avec DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame et EasingDoubleKeyFrame. Vous pouvez utiliser tous et chacun de ces types au sein d'une collection KeyFrames unique, pour modifier l'interpolation chaque fois qu'une nouvelle image clé est atteinte.

Pour le comportement d’interpolation, chaque image clé contrôle l’interpolation jusqu'à ce que son moment KeyTime soit atteint. Sa valeur est également atteinte à ce moment-là. S’il y a plus d’images clés au-delà, la valeur devient la valeur de départ de l’image clé suivante dans une séquence.

Au début de l’animation, si aucune image clé avec KeyTime de « 0:0:0 » existe, la valeur de départ est quelle que soit la valeur non animée de la propriété. Cela est similaire à la façon dont une animation De/To/By agit s'il n’y a pas de De.

La durée d'une animation de trame clé est implicitement égale à la valeur la plus élevée de KeyTime définie dans l'une de ses images clés. Vous pouvez définir une durée explicite si vous le souhaitez, mais soyez prudent à ce qu'elle ne soit pas plus courte qu’un KeyTime dans vos propres images clés, sinon vous couperez une partie de l’animation.

En plus de la durée, vous pouvez définir toutes les propriétés de chronologie basées sur une animation de trame clé, comme vous pouvez avec une animation From/To/By , car les classes d’animation de trame clé dérivent également de Timeline. Ces règles sont les suivantes :

  • AutoReverse : une fois que la dernière image clé est atteinte, les images sont répétées dans l’ordre inverse à partir de la fin. Cela double la durée apparente de l’animation.
  • BeginTime : retarde le début de l’animation. La chronologie des valeurs KeyTime dans les images ne commence pas à compter tant que BeginTime n’est pas atteinte, il n’y a donc aucun risque de couper les images.
  • FillBehavior : contrôle ce qui se passe lorsque la dernière image clé est atteinte. FillBehavior n’a aucun effet sur les images clés intermédiaires.
  • RepeatBehavior :
    • Si la valeur est Forever, les images clés et leur chronologie se répètent infiniment.
    • Si la valeur est définie sur un nombre d’itérations, la chronologie se répète plusieurs fois.
    • Si elle est définie sur une durée, la chronologie se répète jusqu’à ce que cette heure soit atteinte. Cela peut tronquer la partie de l'animation dans la séquence d’images clés, si elle n'est pas un facteur entier de la durée implicite de la chronologie.
  • SpeedRatio (non couramment utilisé)

Images clés linéaires

Les images clés linéaires entraînent une interpolation linéaire simple de la valeur jusqu'à ce que le KeyTime de l'image clé soit atteint. Ce comportement d'interpolation est le plus similaire aux animations From/To/By décrites dans la rubrique Animations Storyboarded.

Voici comment utiliser une animation d'image clé pour scaler la hauteur du rendu d’un rectangle à l’aide d’images clés linéaires. Cet exemple exécute une animation où la hauteur du rectangle augmente légèrement et linéairement pendant les 4 premières secondes, puis effectue une mise à l’échelle rapide pour la dernière seconde jusqu’à ce que le rectangle soit double de la hauteur de départ.

<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>

Images clés distinctes

Les images clés discrètes n’utilisent pas d’interpolation du tout. Lorsqu’un KeyTime est atteint, la nouvelle valeur est simplement appliquée. En fonction de la propriété de l'interface utilisateur qui est animée, cela produit souvent une animation qui donne l'impression de « sauter ». Soyez certain que c’est le comportement esthétique que vous voulez vraiment. Vous pouvez réduire les sauts apparents en augmentant le nombre d’images clés que vous déclarez, mais si une animation fluide est votre objectif, il pourrait être préférable d'utiliser des images clés linéaires ou des splines à la place.

Note

Les images clés discrètes sont la seule façon d’animer une valeur qui n’est pas de type Double, Point et Color, avec un DiscreteObjectKeyFrame. Nous aborderons cela plus en détail plus loin dans cette rubrique.

Trames clés spline

Un frame de clé spline crée une transition de variable entre les valeurs en fonction de la valeur de la propriété KeySpline . Cette propriété spécifie les premiers et deuxième points de contrôle d’une courbe de Bezier, qui décrit l’accélération de l’animation. En fait, une KeySpline définit une relation fonction-temps où le graphique de la fonction est la forme de cette courbe Bézier. Vous spécifiez généralement une valeur KeySpline dans une chaîne d’attribut abrégée XAML qui a quatre valeurs doubles séparées par des espaces ou des virgules. Ces valeurs sont des paires « X, Y » pour deux points de contrôle de la courbe de Bezier. « X » est l’heure et « Y » est le modificateur de fonction de la valeur. Chaque valeur doit toujours être comprise entre 0 et 1 inclus. Sans modification de point de contrôle vers un KeySpline, la ligne droite comprise entre 0,0 et 1,1 est la représentation d’une fonction au fil du temps pour une interpolation linéaire. Vos points de contrôle modifient la forme de cette courbe et donc le comportement de la fonction au fil du temps pour l’animation spline. Il est probablement préférable de voir cela visuellement comme un graphique.

Cet exemple montre trois images clés différentes appliquées à une animation, la dernière étant une animation par courbe spline pour une valeur Double (SplineDoubleKeyFrame). Notez la chaîne « 0.6,0.0 0.9,0.00 » appliquée pour KeySpline. Cela produit une courbe où l’animation semble s’exécuter lentement au début, mais atteint rapidement la valeur juste avant l’atteinte de 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>

Estompage des images clés

Une trame clé d'assouplissement est une trame clé où l'interpolation est appliquée, et la fonction de l'interpolation au fil du temps est contrôlée par plusieurs formules mathématiques prédéfinies. Vous pouvez réellement produire le même résultat avec une trame clé spline que vous pouvez avec certains des types de fonctions d’accélération, mais il existe également certaines fonctions d’accélération, telles que BackEase, que vous ne pouvez pas reproduire avec un spline.

Pour appliquer une fonction d’accélération à une trame clé d’accélération, vous définissez la propriété EasingFunction en tant qu’élément de propriété en XAML pour cette trame clé. Pour la valeur, spécifiez un élément d’objet pour l’un des types de fonctions d’accélération.

Cet exemple applique un CubicEase puis un BounceEase en tant que trames clés successives à un DoubleAnimation pour créer un effet de rebond.

<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>

Il s'agit simplement d'un exemple de fonction de lissage. Nous aborderons plus en détail la section suivante.

Fonctions de lissage

Les fonctions d’accélération vous permettent d’appliquer des formules mathématiques personnalisées à vos animations. Les opérations mathématiques sont souvent utiles pour produire des animations qui simulent la physique réelle dans un système de coordonnées 2D. Par exemple, vous souhaiterez peut-être qu’un objet rebondisse ou se comporte comme s’il était sur un ressort. Vous pouvez utiliser des images clés ou même des animations From/To/By pour estimer ces effets, mais il faudrait une quantité importante de travail et l’animation serait moins précise que l’utilisation d’une formule mathématique.

Les fonctions d’accélération peuvent être appliquées aux animations de trois façons :

Voici une liste des fonctions de lissage :

  • BackEase : rétracte légèrement le mouvement d’une animation avant qu’elle ne commence à s’animer dans le chemin indiqué.
  • BounceEase : crée un effet de rebond.
  • CircleEase : crée une animation qui accélère ou décélére à l’aide d’une fonction circulaire.
  • CubeEase : crée une animation qui accélère ou décélérée à l’aide de la formule f(t) = t3.
  • ElasticEase : crée une animation qui ressemble à un ressort oscillant de retour et d’avant jusqu’à ce qu’il arrive au repos.
  • ExponentialEase : crée une animation qui accélère ou décélère à l’aide d’une formule exponentielle.
  • PowerEase : crée une animation qui accélère ou décélérée à l’aide de la formule f(t) = tp où p est égal à la propriété Power .
  • QuadraticEase : crée une animation qui accélère ou décélérée à l’aide de la formule f(t) = t2.
  • QuarticEase : crée une animation qui accélère ou décélérée à l’aide de la formule f(t) = t4.
  • QuinticEase : créez une animation qui accélère ou décélére à l’aide de la formule f(t) = t5.
  • SineEase : crée une animation qui accélère ou décélère à l’aide d’une formule sinusoïdale.

Certaines des fonctions d'assouplissement ont leurs propres propriétés. Par exemple, BounceEase a deux propriétés Bounces et Bounciness qui modifient le comportement de fonction au fil du temps de ce BounceEase particulier. D’autres fonctions d’accélération telles que CubicEase n’ont pas de propriétés autres que la propriété EasingMode que toutes les fonctions d’accélération partagent et produisent toujours le même comportement de fonction au fil du temps.

Certaines de ces fonctions de lissage présentent un certain chevauchement, selon la manière dont vous définissez les propriétés sur les fonctions de lissage qui ont des propriétés. Par exemple, QuadraticEase est exactement la même qu’une PowerEase avec Power égale à 2. Et CircleEase est essentiellement un ExponentialEase avec une valeur par défaut.

La fonction d’accélération BackEase est unique, car elle peut modifier la valeur en dehors de la plage normale telle qu’elle est définie par From/To ou les valeurs des images clés. Elle démarre l'animation en modifiant la valeur dans la direction opposée à celle prévue par un comportement De/À normal, revient à la valeur initiale ou de départ, puis exécute l'animation comme normalement.

Dans un exemple précédent, nous avons montré comment déclarer une fonction d’accélération pour une animation clé-image. Cet exemple suivant applique une fonction d’accélération à une animation 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>

Lorsqu’une fonction d’accélération est appliquée à une animation FromTo/By, elle modifie les caractéristiques temporelles de la façon dont la valeur interpole entre les / valeurs From et To sur la durée de l’animation. Sans fonction d’accélération, il s’agirait d’une interpolation linéaire.

Animations de valeur d’objet discrètes

Un type d’animation mérite une mention spéciale, car c’est la seule façon dont vous pouvez appliquer une valeur animée aux propriétés qui ne sont pas de type Double, Point ou Color. Voici l’animation de point clé ObjectAnimationUsingKeyFrames. L’animation à l’aide de valeurs d’objet est différente, car il n’existe aucune possibilité d’interpoler les valeurs entre les images. Lorsque le KeyTime de la trame est atteint, la valeur animée est immédiatement définie sur la Value spécifiée dans l’image clé. Comme il n’existe aucune interpolation, il n’existe qu’une seule image clé que vous utilisez dans la collection d’images clés ObjectAnimationUsingKeyFrames : DiscreteObjectKeyFrame.

La valeur d’un objet DiscreteObjectKeyFrame est souvent définie à l’aide de la syntaxe de l’élément de propriété, car la valeur de l’objet que vous essayez de définir n’est souvent pas expressible sous forme de chaîne pour remplir la syntaxe d’attribut . Vous pouvez toujours utiliser la syntaxe d’attribut si vous utilisez une référence telle que StaticResource.

Un emplacement où vous verrez un ObjectAnimationUsingKeyFrames utilisé dans les modèles par défaut est lorsqu’une propriété de modèle fait référence à une ressource Brush . Ces ressources sont des objets SolidColorBrush , pas seulement une valeur Color et utilisent des ressources définies comme thèmes système (ThemeDictionaries). Elles peuvent être affectées directement à une valeur de type Brush, telle que TextBlock.Foreground , et n’ont pas besoin d’utiliser le ciblage indirect. Toutefois, étant donné qu’un SolidColorBrush n’est pas double, point ou couleur, vous devez utiliser un ObjectAnimationUsingKeyFrames pour utiliser la ressource.

<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>

Vous pouvez également utiliser ObjectAnimationUsingKeyFrames pour animer des propriétés qui utilisent une valeur d’énumération. Voici un autre exemple d’un style nommé qui provient des modèles par défaut Windows Runtime. Notez comment elle définit la propriété Visibility qui prend une constante d’énumération Visibility . Dans ce cas, vous pouvez définir la valeur à l’aide de la syntaxe d’attribut. Vous avez uniquement besoin du nom de constante non qualifié d’une énumération pour définir une propriété avec une valeur d’énumération, par exemple « Collapsed ».

<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>

Vous pouvez utiliser plusieurs DiscreteObjectKeyFrame pour un ObjectAnimationUsingKeyFrames. Il peut s’agir d’un moyen intéressant de créer une animation « diaporama » en animant la valeur d’Image.Source, comme exemple de scénario pour lequel plusieurs valeurs d’objet peuvent être utiles.