Animazioni di fotogrammi chiave e funzioni di interpolazione
Le animazioni con fotogrammi chiave lineari, le animazioni con fotogrammi chiave con un valore KeySpline o le funzioni di interpolazione sono tre tecniche diverse per circa lo stesso scenario: la creazione di un'animazione con storyboard leggermente più complessa e che usa un comportamento di animazione non lineare da uno stato iniziale a uno stato finale.
Prerequisiti
Assicurarsi di aver letto l'argomento Animazioni con storyboard. Questo argomento si basa sui concetti di animazione illustrati nelle animazioni con storyboard e non li rilascerà di nuovo. Ad esempio, le animazioni con storyboard descrivono come impostare come destinazione animazioni, storyboard come risorse, i valori delle proprietà Timeline, ad esempio Durata, FillBehavior e così via.
Animazione con animazioni con fotogrammi chiave
Le animazioni con fotogrammi chiave consentono più di un valore di destinazione raggiunto in un punto lungo la sequenza temporale dell'animazione. In altre parole, ogni fotogramma chiave può specificare un valore intermedio diverso e l'ultimo fotogramma chiave raggiunto è il valore di animazione finale. Specificando più valori da animare, è possibile rendere più complesse le animazioni. Le animazioni con fotogrammi chiave abilitano anche una logica di interpolazione diversa, ognuna implementata come sottoclasse KeyFrame diversa per ogni tipo di animazione. In particolare, ogni tipo di animazione con fotogrammi chiave ha una variante Discrete, Linear, Spline e Interpolazione della relativa classe KeyFrame per specificare i fotogrammi chiave. Ad esempio, per specificare un'animazione destinata a Double e usa fotogrammi chiave, è possibile dichiarare fotogrammi chiave con DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame, e EasingDoubleKeyFrame. È possibile usare qualsiasi tipo e tutti questi tipi all'interno di una singola raccolta KeyFrames per modificare l'interpolazione ogni volta che viene raggiunto un nuovo fotogramma chiave.
Per il comportamento di interpolazione, ogni fotogramma chiave controlla l'interpolazione fino al raggiungimento del tempo KeyTime . Il valore viene raggiunto anche in quel momento. Se sono presenti più fotogrammi chiave oltre, il valore diventa il valore iniziale per il fotogramma chiave successivo in una sequenza.
All'inizio dell'animazione, se non esiste alcun fotogramma chiave con KeyTime "0:0:0", il valore iniziale è qualsiasi valore non animato della proprietà. Questo è simile al modo in cui un'animazione From/To/By agisce se non c'è From.
La durata di un'animazione con fotogrammi chiave è implicitamente la durata uguale al valore KeyTime massimo impostato in uno dei fotogrammi chiave. Puoi impostare una durata esplicita se vuoi, ma fai attenzione che non sia più breve di un KeyTime nei tuoi fotogrammi chiave o vuoi tagliare parte dell'animazione.
Oltre alla durata, puoi impostare tutte le proprietà basate su Sequenza temporaleTimeline su un'animazione con fotogrammi chiave, come puoi usare un'animazione From/To/By, perché anche le classi di animazione con fotogrammi chiave derivano da Timeline. Si tratta di:
- AutoReverse: una volta raggiunto l'ultimo fotogramma chiave, i fotogrammi vengono ripetuti in ordine inverso dalla fine. Ciò raddoppia la durata apparente dell'animazione.
- BeginTime: ritarda l'inizio dell'animazione. La sequenza temporale per i valori KeyTime nei fotogrammi non inizia a contare fino al raggiungimento di BeginTime , quindi non c'è alcun rischio di taglio dei fotogrammi
- FillBehavior: controlla cosa accade quando viene raggiunto l'ultimo fotogramma chiave. FillBehavior non ha alcun effetto sui fotogrammi chiave intermedi.
- RepeatBehavior:
- Se impostato su Forever, i fotogrammi chiave e la sequenza temporale si ripetono infinitamente.
- Se impostato su un conteggio di iterazioni, la sequenza temporale viene ripetuta molte volte.
- Se è impostato su una durata, la sequenza temporale viene ripetuta fino a quando non viene raggiunto tale tempo. Ciò potrebbe troncare la parte dell'animazione attraverso la sequenza di fotogrammi chiave, se non è un fattore intero della durata implicita della sequenza temporale.
- SpeedRatio (non comunemente usato)
Fotogrammi chiave lineari
I fotogrammi chiave lineari generano una semplice interpolazione lineare del valore fino a quando non viene raggiunto il valore KeyTime del fotogramma. Questo comportamento di interpolazione è il più simile alle animazioni From/To/By più semplici descritte nell'argomento Animazioni con storyboard.
Ecco come usare un'animazione con fotogrammi chiave per ridimensionare l'altezza di rendering di un rettangolo, usando fotogrammi chiave lineari. In questo esempio viene eseguita un'animazione in cui l'altezza del rettangolo aumenta leggermente e linearmente per i primi 4 secondi, quindi si ridimensiona rapidamente per l'ultimo secondo fino a quando il rettangolo non raddoppia l'altezza iniziale.
<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>
Fotogrammi chiave discreti
I fotogrammi chiave discreti non usano affatto alcuna interpolazione. Quando viene raggiunto un valore KeyTime , il nuovo valore viene semplicemente applicato. A seconda della proprietà dell'interfaccia utente animata, questo produce spesso un'animazione che sembra "jump". Assicurati che questo sia il comportamento estetico che vuoi davvero. Puoi ridurre al minimo i salti apparenti aumentando il numero di fotogrammi chiave dichiarati, ma se un'animazione fluida è il tuo obiettivo, potresti essere meglio usare fotogrammi chiave lineari o spline.
Nota
I fotogrammi chiave discreti sono l'unico modo per animare un valore che non è di tipo Double, Point, e Color, con DiscreteObjectKeyFrame.. Ciò verrà trattato in modo più dettagliato più avanti in questo argomento.
Fotogrammi chiave spline
Un fotogramma chiave spline crea una transizione variabile tra i valori in base al valore della proprietà KeySpline. Questa proprietà specifica il primo e il secondo punto di controllo di una curva di Bézier, che descrive l'accelerazione dell'animazione. Fondamentalmente, una keySpline definisce una relazione di funzione nel tempo in cui il grafico temporizzato è la forma della curva di Bézier. In genere si specifica un valore KeySpline in una stringa di attributo abbreviata XAML con quattro valori Double separati da spazi o virgole. Questi valori sono coppie "X,Y" per due punti di controllo della curva di Bézier. "X" è l'ora e "Y" è il modificatore di funzione per il valore. Ogni valore deve essere sempre compreso tra 0 e 1 inclusi. Senza la modifica del punto di controllo in una keySpline, la linea retta da 0,0 a 1,1 è la rappresentazione di una funzione nel tempo per un'interpolazione lineare. I punti di controllo modificano la forma di tale curva e quindi il comportamento della funzione nel tempo per l'animazione spline. È probabilmente preferibile vedere questo aspetto visivamente come grafico. È possibile eseguire l'esempio del visualizzatore key-spline di Silverlight in un browser per vedere come i punti di controllo modificano la curva e come viene eseguita un'animazione di esempio quando viene usata come valore KeySpline.
Questo esempio seguente mostra tre fotogrammi chiave diversi applicati a un'animazione, con l'ultimo che rappresenta un'animazione spline chiave per un valore Double (SplineDoubleKeyFrame). Si noti la stringa "0.6.0.0 0.9,0.00" applicata per KeySpline. Ciò produce una curva in cui l'animazione sembra essere eseguita lentamente all'inizio, ma poi raggiunge rapidamente il valore appena prima che venga raggiunto 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>
Interpolazione di fotogrammi chiave
Un fotogramma chiave di interpolazione è un fotogramma chiave in cui viene applicata l'interpolazione e la funzione nel tempo dell'interpolazione è controllata da diverse formule matematiche predefinite. In realtà è possibile produrre molto lo stesso risultato con un fotogramma chiave spline come è possibile con alcuni dei tipi di funzione di interpolazione, ma esistono anche alcune funzioni di interpolazione, ad esempio BackEase, che non è possibile riprodurre con una spline.
Per applicare una funzione di interpolazione a un fotogramma chiave di interpolazione, imposta la proprietà EasingFunction come elemento proprietà in XAML per tale fotogramma chiave. Per il valore specificare un elemento oggetto per uno dei tipi di funzione di interpolazione.
In questo esempio viene applicato un valore CubicEase e quindi BounceEase come fotogrammi chiave successivi a un DoubleAnimation per creare un effetto rimbalzante.
<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>
Questo è solo un esempio di funzione di interpolazione. Nella sezione successiva verranno illustrate altre informazioni.
Funzioni di interpolazione
Le funzioni di interpolazione consentono di applicare formule matematiche personalizzate alle animazioni. Le operazioni matematiche sono spesso utili per produrre animazioni che simulano la fisica reale in un sistema di coordinate 2D. Si può ad esempio fare in modo che un oggetto rimbalzi in modo realistico o si comporti come se fosse su una molla. È possibile usare animazioni con fotogrammi chiave o anche animazioni From/To/By per simulare questi effetti, ma l'operazione richiederebbe una quantità significativa di lavoro e l'animazione risulterebbe meno accurata rispetto all'uso di una formula matematica.
Le funzioni di interpolazione possono essere applicate alle animazioni in tre modi:
- Usando un fotogramma chiave di interpolazione in un'animazione basata su fotogrammi chiave, come descritto nella sezione precedente. Usare EasingColorKeyFrame.EasingFunction, EasingDoubleKeyFrame.EasingFunction, o EasingPointKeyFrame.EasingFunction.
- Impostando la proprietà EasingFunction su uno dei tipi di animazione From/To/By. Usare ColorAnimation.EasingFunction, DoubleAnimation.EasingFunction o PointAnimation.EasingFunction.
- Impostando GeneratedEasingFunction come parte di un oggetto VisualTransition. Questo è specifico per definire gli stati di visualizzazione per i controlli; per altre info, vedi GeneratedEasingFunction o Storyboards per gli stati di visualizzazione.
Segue un elenco delle funzioni interessate.
- BackEase: ritrae il movimento di un'animazione poco prima che inizi ad animarsi nel tracciato indicato.
- BounceEase: crea un effetto rimbalzante.
- CircleEase: crea un'animazione che accelera o decelera utilizzando una funzione circolare.
- CubicEase: crea un'animazione che accelera o decelerate usando la formula f(t) = t3.
- ElasticEase: crea un'animazione simile a una molla che oscilla avanti e indietro fino ad arrestarsi.
- ExponentialEase: crea un'animazione che accelera o decelera utilizzando una formula esponenziale.
- PowerEase: crea un'animazione che accelera o decelerate usando la formula f(t) = tp dove p è uguale alla proprietà Power .
- QuadraticEase: crea un'animazione che accelera o decelerate usando la formula f(t) = t2.
- QuadraticEase: crea un'animazione che accelera o decelerate usando la formula f(t) = t4.
- QuinticEase: crea un'animazione che accelera o decelerate usando la formula f(t) = t5.
- SineEase: crea un'animazione che accelera o decelera usando una formula seno.
Alcune delle funzioni di interpolazione hanno proprietà specifiche. Ad esempio, BounceEase ha due proprietà Bounces e Bounciness che modificano il comportamento della funzione nel tempo di quel particolare BounceEase. Altre funzioni di interpolazione, ad esempio CubicEase, non hanno proprietà diverse dalla proprietà EasingMode che tutte le funzioni di interpolazione condividono e producono sempre lo stesso comportamento di funzione nel tempo.
Alcune di queste funzioni di interpolazione presentano una certa sovrapposizione, a seconda della modalità di impostazione delle proprietà sulle funzioni di interpolazione con proprietà. Ad esempio, QuadraticEase è esattamente uguale a PowerEase con Power uguale a 2. E CircleEase è fondamentalmente un valore predefinito ExponentialEase.
La funzione di interpolazione BackEase è univoca perché può modificare il valore all'esterno dell'intervallo normale impostato da From/To o i valori dei fotogrammi chiave. Avvia l'animazione modificando il valore nella direzione opposta come previsto da un normale comportamento From/To, torna al valore From o iniziale e quindi esegue l'animazione come di consueto.
In un esempio precedente è stato illustrato come dichiarare una funzione di interpolazione per un'animazione con fotogrammi chiave. Questo esempio successivo applica una funzione di interpolazione a un'animazione 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>
Quando una funzione di interpolazione viene applicata a un'animazione From/To/By, modifica le caratteristiche della funzione nel tempo del modo in cui il valore esegue l'interpolazione tra i valori From e To nella durata dell'animazione. Senza una funzione di interpolazione, si tratta di un'interpolazione lineare.
Animazioni con valori di oggetto discreti
Un tipo di animazione merita una menzione speciale perché è l'unico modo per applicare un valore animato alle proprietà che non sono di tipo Double, Point, o Color. Questa è l'animazione con fotogrammi chiave ObjectAnimationUsingKeyFrames. L'animazione con i valori object è diversa perché non è possibile interpolare i valori tra i fotogrammi. Quando viene raggiunto il valore KeyTime del fotogramma, il valore animato viene immediatamente impostato sul valore specificato nel valore del fotogramma chiave Valore. Poiché non esiste alcuna interpolazione, è presente un solo fotogramma chiave usato nell'insieme di fotogrammi chiave ObjectAnimationUsingKeyFrames: DiscreteObjectKeyFrames.
Il valore di un Oggetto DiscreteObjectKeyFrame viene spesso impostato usando la sintassi degli elementi di proprietà, perché il valore dell'oggetto che si sta tentando di impostare spesso non è expressible come stringa per inserire Value nella sintassi degli attributi. È comunque possibile usare la sintassi degli attributi se si usa un riferimento, ad esempio StaticResource.
Una posizione in cui verrà visualizzato un ObjectAnimationUsingKeyFrames usato nei modelli predefiniti è quando una proprietà modello fa riferimento a una risorsa Brush. Queste risorse sono oggetti SolidColorBrush, non solo un valore Color e usano risorse definite come temi di sistema (ThemeDictionariess). Possono essere assegnati direttamente a un valore di tipo Brush, ad esempio TextBlock.Foreground e non è necessario usare la destinazione indiretta. Tuttavia, poiché SolidColorBrush non è Double, Point, o Color, si deve usare ObjectAnimationUsingKeyFrames per usare la risorsa.
<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>
È anche possibile usare ObjectAnimationUsingKeyFrames per animare le proprietà che usano un valore di enumerazione. Ecco un altro esempio di uno stile denominato proveniente dai modelli predefiniti di Windows Runtime. Si noti come imposta la proprietà Visibility che accetta una costante di enumerazione Visibility. In questo caso è possibile impostare il valore usando la sintassi dell'attributo. È necessario solo il nome di costante non qualificato da un'enumerazione per impostare una proprietà con un valore di enumerazione, ad esempio "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>
È possibile usare più di un DiscreteObjectKeyFrame per un set di fotogrammi ObjectAnimationUsingKeyFrames. Questo potrebbe essere un modo interessante per creare un'animazione "presentazione" animando il valore di Image.Source, come scenario di esempio per cui potrebbero essere utili più valori di oggetto.