Delen via


Animaties voor sleutelframes en animaties voor easing-functies

Lineaire sleutelframeanimaties, sleutelframeanimaties met een KeySpline-waarde of easing-functies zijn drie verschillende technieken voor ongeveer hetzelfde scenario: het maken van een storyboarded animatie die iets complexer is en dat gebruikmaakt van een niet-lineair animatiegedrag van een beginstatus tot een eindstatus.

Vereiste voorwaarden

Zorg ervoor dat u het onderwerp Storyboarded animaties hebt gelezen. Dit onderwerp bouwt voort op de animatieconcepten die zijn uitgelegd in Storyboarded-animaties en gaan ze niet opnieuw over. Met storyboarded animaties wordt bijvoorbeeld beschreven hoe u animaties kunt toewijzen, storyboards als resources kunt gebruiken, de waarden van de eigenschap Tijdlijn, zoals Duur, Vulgedrag, enzovoort.

Animeren met behulp van sleutelbeeld-animaties

Met keyframe-animaties kunnen meer dan één doelwaarde worden bereikt op een punt langs de animatietijdlijn. Met andere woorden, elk sleutelframe kan een andere tussenliggende waarde opgeven en het laatste sleutelframe dat is bereikt, is de uiteindelijke animatiewaarde. Door meerdere waarden op te geven voor animatie, kunt u complexere animaties maken. Met keyframe-animaties kunt u ook verschillende interpolatielogica inschakelen, die elk worden geïmplementeerd als een andere KeyFrame-subklasse per animatietype. Elk type keyframe-animatie heeft een discrete, lineaire, spline- en easing-variatie van de Keyframeklasse voor het opgeven van de sleutelframes. Als u bijvoorbeeld een animatie wilt opgeven die gericht is op een double en sleutelframes gebruikt, kunt u sleutelframes declareren met DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame en EasingDoubleKeyFrame. U kunt elk van deze typen in één KeyFrames-verzameling gebruiken om de interpolatie te wijzigen telkens wanneer een nieuw sleutelframe wordt bereikt.

Voor interpolatiegedrag bepaalt elk sleutelframe de interpolatie totdat de KeyTime-tijd is bereikt. De waarde wordt dan ook bereikt op dat moment. Als er meer sleutelframes voorbij zijn, wordt de waarde de beginwaarde voor het volgende sleutelframe in een reeks.

Als aan het begin van de animatie geen sleutelframe met KeyTime van '0:0:0' bestaat, is de beginwaarde ongeacht de niet-geanimeerde waarde van de eigenschap. Dit is vergelijkbaar met hoe een animatie van Van naar / werkt wanneer er geen Van is.

De duur van een sleutelframeanimatie is impliciet de duur die gelijk is aan de hoogste KeyTime-waarde die is ingesteld in een van de sleutelframes. U kunt desgewenst een expliciete duur instellen, maar pas op dat het niet korter is dan een KeyTime in uw eigen sleutelframes of u snijdt een deel van de animatie af.

Naast Duur kunt u alle tijdlijngebaseerde eigenschappen instellen op een sleutelframe-animatie, zoals u dat kunt met een Van/Naar//Door animatie, omdat de sleutelframe-animatieklassen ook zijn afgeleid van de tijdlijn./ Dit zijn:

  • AutoReverse: zodra het laatste sleutelframe is bereikt, worden de frames herhaald in omgekeerde volgorde vanaf het einde. Dit verdubbelt de schijnbare duur van de animatie.
  • BeginTime: hiermee wordt het begin van de animatie vertraagd. De tijdlijn voor de KeyTime-waarden in de frames begint niet te tellen totdat BeginTime is bereikt, dus er is geen risico dat frames worden afgekapt
  • FillBehavior: bepaalt wat er gebeurt wanneer het laatste sleutelframe wordt bereikt. FillBehavior heeft geen effect op tussenliggende sleutelframes.
  • RepeatBehavior:
    • Als deze optie is ingesteld op Forever, worden de belangrijkste frames en hun tijdlijn oneindig herhaald.
    • Als deze optie is ingesteld op een herhalingsaantal, herhaalt de tijdlijn dat vaak.
    • Als deze optie is ingesteld op een duur, wordt de tijdlijn herhaald tot die tijd is bereikt. Daardoor kan de animatie halverwege worden afgebroken in de reeks sleutelframes, als de tijdlijn niet een geheel veelvoud is van de impliciete duur.
  • SpeedRatio (niet vaak gebruikt)

Lineaire sleutelframes

Lineaire sleutelframes resulteren in een eenvoudige lineaire interpolatie van de waarde totdat de KeyTime van het frame is bereikt. Dit interpolatiegedrag lijkt het meest op de eenvoudigere From/To/By-animaties beschreven in het onderwerp Storyboarded animations.

U kunt als volgt een sleutelframeanimatie gebruiken om de hoogte van een rechthoek te schalen met behulp van lineaire sleutelframes. In dit voorbeeld wordt een animatie uitgevoerd waarbij de hoogte van de rechthoek gedurende de eerste 4 seconden enigszins en lineair toeneemt en vervolgens snel wordt geschaald voor de laatste seconde totdat de rechthoek dubbele beginhoogte heeft.

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

Discrete sleutelbeelden

Discrete sleutelframes gebruiken helemaal geen interpolatie. Wanneer een KeyTime is bereikt, wordt de nieuwe waarde gewoon toegepast. Afhankelijk van welke ui-eigenschap wordt geanimeerd, produceert dit vaak een animatie die lijkt te springen. Wees er zeker van dat dit het esthetische gedrag is dat je echt wilt. U kunt de schijnbare sprongen minimaliseren door het aantal sleutelframes dat u declareert te verhogen, maar als een vloeiende animatie uw doel is, kunt u in plaats daarvan beter lineaire of spline-sleutelframes gebruiken.

Opmerking

Discrete sleutelframes zijn de enige manier om een waarde te animeren die niet van het type Double, Point en Color is, met een DiscreteObjectKeyFrame. We bespreken dit later in dit onderwerp in meer detail.

Spline-sleutelframes

Een spline-sleutelframe maakt een variabeleovergang tussen waarden op basis van de waarde van de eigenschap KeySpline . Met deze eigenschap worden de eerste en tweede besturingspunten van een Bezier-curve opgegeven, waarin de versnelling van de animatie wordt beschreven. In feite definieert een KeySpline een functie-over-tijd-relatie waarbij de grafiek van de functie-tijd de vorm van die Bezier-curve is. Normaal gesproken geeft u een KeySpline-waarde op in een XAML-tekenreeks met vier dubbele waarden gescheiden door spaties of komma's. Deze waarden zijn X,Y-paren voor twee besturingspunten van de Bezier-curve. 'X' is tijd en 'Y' is de functieaanpassing voor de waarde. Elke waarde moet altijd tussen 0 en 1 inclusief zijn. Zonder wijziging van het besturingspunt in een KeySpline is de rechte lijn van 0,0 tot 1,1 de weergave van een functie in de loop van de tijd voor een lineaire interpolatie. De besturingspunten veranderen de vorm van die curve en dus het gedrag van de functie in de loop van de tijd voor de splineanimatie. Het is waarschijnlijk het beste om dit visueel te zien als een grafiek.

In dit volgende voorbeeld ziet u drie verschillende sleutelframes die zijn toegepast op een animatie, waarbij de laatste een spline-animatie voor een dubbele waarde (SplineDoubleKeyFrame) is. Noteer de tekenreeks '0,6,0.0 0.9,0.00' die is toegepast op KeySpline. Dit produceert een curve waarbij de animatie eerst langzaam wordt uitgevoerd, maar vervolgens de waarde snel bereikt vlak voordat de KeyTime wordt bereikt.

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

Sleutelframes versoepelen

Een versoepelingssleutelframe is een sleutelframe waarin interpolatie wordt toegepast en de functie in de loop van de tijd van de interpolatie wordt bepaald door verschillende vooraf gedefinieerde wiskundige formules. U kunt eigenlijk hetzelfde resultaat produceren met een spline-sleutelframe zoals u kunt met een aantal van de typen easing-functies, maar er zijn ook enkele easing-functies, zoals BackEase, die u niet kunt reproduceren met een spline.

Als u een easing-functie wilt toepassen op een easing-sleutelframe, stelt u de eigenschap EasingFunction in als een eigenschapselement in XAML voor dat sleutelframe. Geef voor de waarde een objectelement op voor een van de typen easing-functies.

In dit voorbeeld wordt een CubicEase en vervolgens een BounceEase als opeenvolgende sleutelframes toegepast op een DoubleAnimation om een bouncing-effect te maken.

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

Dit is slechts één voorbeeld van een easing-functie. In de volgende sectie vindt u meer informatie.

Easing-functies

Met easing-functies kunt u aangepaste wiskundige formules toepassen op uw animaties. Wiskundige bewerkingen zijn vaak handig om animaties te produceren die echte natuurkunde simuleren in een 2D-coördinaatsysteem. U wilt bijvoorbeeld dat een object realistisch stuitert of zich gedraagt alsof het op een veer staat. U kunt een sleutelframe of zelfs Van/Naar/Door-animaties gebruiken om deze effecten te benaderen, maar het zou veel werk kosten en de animatie zou minder nauwkeurig zijn dan wanneer je een wiskundige formule zou gebruiken.

Easing-functies kunnen op drie manieren worden toegepast op animaties:

Hier is een lijst van de easing-functies:

  • BackEase: Trekt de beweging van een animatie iets in voordat deze animatie begint te animeren in het aangegeven pad.
  • BounceEase: Hiermee wordt een bouncing-effect gemaakt.
  • CircleEase: Hiermee maakt u een animatie die versnelt of vertraagt met behulp van een kringfunctie.
  • CubicEase: Hiermee maakt u een animatie waarmee de formule f(t) = t3 wordt versneld of vertraagd.
  • ElasticEase: Hiermee maakt u een animatie die lijkt op een veer die heen en weer draait totdat het tot rust komt.
  • ExponentialEase: Hiermee maakt u een animatie die versnelt of vertraagt met behulp van een exponentiële formule.
  • PowerEase: Hiermee maakt u een animatie die versnelt of vertraagt met behulp van de formule f(t) = tp waarbij p gelijk is aan de eigenschap Power .
  • QuadraticEase: Hiermee maakt u een animatie waarmee de formule f(t) = t2 wordt versneld of vertraagd.
  • QuarticEase: Hiermee maakt u een animatie waarmee de formule f(t) = t4 wordt versneld of vertraagd.
  • QuinticEase: Maak een animatie waarmee de formule f(t) = t5 wordt versneld of vertraagd.
  • SineEase: Hiermee maakt u een animatie die versnelt of vertraagt met behulp van een sinusformule.

Sommige easing-functies hebben hun eigen eigenschappen. BounceEase heeft bijvoorbeeld twee eigenschappen Bounces en Bounciness die het gedrag van de functie in de loop van de tijd van die specifieke BounceEase wijzigen. Andere easing-functies, zoals CubicEase , hebben geen andere eigenschappen dan de eigenschap EasingMode die alle easing functions delen en produceren altijd hetzelfde gedrag in de loop van de tijd.

Sommige van deze easing-functies overlappen enigszins, afhankelijk van hoe u eigenschappen instelt voor de easing-functies die eigenschappen hebben. QuadraticEase is bijvoorbeeld precies hetzelfde als een PowerEase met Power gelijk aan 2. CircleEase is in feite een standaardwaarde ExponentialEase.

De functie BackEase-versoepeling is uniek omdat deze de waarde buiten het normale bereik kan wijzigen, zoals ingesteld door From/To of waarden van sleutelframes. De animatie begint met het wijzigen van de waarde in de tegenovergestelde richting dan gebruikelijk is bij een normaal Van/Naar gedrag, keert vervolgens terug naar de Van- of startwaarde, en voert daarna de animatie zoals gebruikelijk uit.

In een eerder voorbeeld hebben we laten zien hoe we een versoepelingsfunctie declareren voor een sleutelframeanimatie. In dit volgende voorbeeld wordt een easing-functie toegepast op een From/To/By animatie.

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

Wanneer een verzachtende functie wordt toegepast op een From/To/By animatie, verandert het de functie-in-de-loop-van-de-tijd kenmerken van hoe de waarde interpoleert tussen de Van en Naar waarden gedurende de duur van de animatie. Zonder een versoepelingsfunctie zou dat een lineaire interpolatie zijn.

Animaties voor discrete objectwaarden

Eén type animatie verdient speciale vermelding omdat dit de enige manier is om een animatiewaarde toe te passen op eigenschappen die niet van het type Double, Point of Color zijn. Dit is de keyframe-animatie ObjectAnimationUsingKeyFrames. Het gebruik van objectwaarden is anders omdat er geen mogelijkheid is om de waarden tussen de frames te interpoleren. Wanneer de KeyTime van het frame is bereikt, wordt de geanimeerde waarde onmiddellijk ingesteld op de waarde die is opgegeven in de Value van het sleutelframe. Omdat er geen interpolatie is, is er slechts één sleutelframe dat u gebruikt in de sleutelframeverzameling ObjectAnimationUsingKeyFrames : DiscreteObjectKeyFrame.

De waarde van een DiscreteObjectKeyFrame wordt vaak ingesteld met de syntaxis van het eigenschapselement, omdat de objectwaarde die u probeert in te stellen vaak niet wordt weergegeven als een tekenreeks om waarde in kenmerksyntaxis in te vullen. U kunt nog steeds kenmerksyntaxis gebruiken als u een verwijzing zoals StaticResource gebruikt.

Een plaats waar je een ObjectAnimationUsingKeyFrames gebruikt ziet in de standaardsjabloon, is wanneer een sjablooneigenschap verwijst naar een Brush-resource. Deze resources zijn SolidColorBrush-objecten , niet alleen een kleurwaarde , en ze gebruiken resources die zijn gedefinieerd als systeemthema's (ThemeDictionaries). Ze kunnen rechtstreeks worden toegewezen aan een kwasttypewaarde zoals TextBlock.Foreground en hoeven geen indirecte targeting te gebruiken. Maar omdat een SolidColorBrush niet Double, Point of Color is, moet u een ObjectAnimationUsingKeyFrames gebruiken om de resource te gebruiken.

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

U kunt ook ObjectAnimationUsingKeyFrames gebruiken om eigenschappen te animeren die gebruikmaken van een opsommingswaarde. Hier volgt een ander voorbeeld van een benoemde stijl die afkomstig is van de standaardsjablonen van Windows Runtime. U ziet hoe de eigenschap Zichtbaarheid wordt ingesteld die een opsommingsconstante Zichtbaarheid gebruikt. In dit geval kunt u de waarde instellen met behulp van de syntaxis van het kenmerk. U hebt alleen de ongekwalificeerde constant naam uit een opsomming nodig voor het instellen van een eigenschap met een opsommingswaarde, bijvoorbeeld '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>

U kunt meer dan één DiscreteObjectKeyFrame gebruiken voor een ObjectAnimationUsingKeyFrames-frameset . Dit kan een interessante manier zijn om een 'diavoorstelling'-animatie te maken door de waarde van Image.Source aan te geven, zoals een voorbeeldscenario waarin meerdere objectwaarden nuttig kunnen zijn.