Animacje w WPF pozwalają na zmianę wartości właściwości obiektów w określonym czasie. Można zmieniać kolor, rozmiar, położenie albo jakąkolwiek inną właściwość związaną z daną kontrolką.
Animację można podzielić na 3 grupy
- Liniowe (linear) - pozwalają na zmianę w liniowy sposób danej właściwości. Nazwy rozpoczynają się od <TypeName>Animation np. DoubleAnimation, przedrostek TypeName jest nazwą typu animacji.
- Klatkowe (frame) - animacja jest zdefiniowana jako osobne klatki pojawiające się w zdefiniowanym czasie i mające zdefiniowaną wartość. Nazewnictwo: <TypeName>AnimationUsingKeyFrames np. StringAnimationUsingKeyFrames
- "Ścieżkowe" - (Path based) - tłumaczenie polskie niezbyt dobre jednak chodzi o definiowanie animacji za pomocą obiektu typu Path. Najczęściej używane w przypadku zmiany położenia obiektu na formatce. Nazewnictwo: <TypeName>AnimationUsingPath np. PointAnimationUsingPath
Podstawowe właściwości, które można znaleźć w klasach odpowiedzialnych za animacje:
- AccelerationRatio - określa jak w czasie zostanie przyśpieszona zmiana wartości animowanej właściwości
- AutoReverse - określa czy animacja ma być odtwarzana od tyłu po jej zakończeniu
- BeginTime - określa relatywny czas rozpoczęcia animacji. Dla przykładu: ustawienie tej właściwości na wartość 0:0:5 spowoduje że jej odtwarzanie nastąpi po 5 sekundach od jej uaktywnienia
- DecelerationRatio - określa w jakim tempie animacja będzie zwalniała podczas wracania do punktu startowego
- Duration - czas trwania animacji
- FillBehavior - określa co ma się stać po zakończeniu animacji
- RepeatBehavior - określa sposób powtarzania animacji
- SpeedRatio - określa stosunek w jakim dana animacja wykonuje postęp w stosunku do jej rodzica
- From - określa wartość początkową - jeżeli pominiemy będzie użyta aktualna
- To - wartość końcowa
- By - określa czas przez który dana właściwość będzie zmieniana - jeżeli jest ustawiona właściwość To, By jest pomijane
Storyboard
Steruje i kontroluje animacją. W właściwości
Children przechowuje obiekty typu
Timeline, które zawierają w sobie obiekty Animacji.
Deklaracja:
Code:
<Storyboard TargetName="Button" TargetProperty="Height">
<DoubleAnimation Duration="0:0:10" From="1" To="200" />
</Storyboard>
Jako że
TargetName oraz
TargetProperty są właściwościami typu
attached można także przypiąć je do odpowiedniego elementu:
Code:
<Storyboard>
<DoubleAnimation Duration="0:0:10" From="1" To="200" Storyboard.TargetName="Button" Storyboard.TargetProperty="Height" />
</Storyboard>
Jest to preferowane rozwiązanie, gdyż w większości przypadków StoryBoard będzie zawierał więcej niż jedną animację na raz.
Użycie animacji wraz z triggerami
Aby animacja mogła być uruchomiona można użyć np. triggerów. Ich użycie może być na jeden z dwóch sposobów:
- style
- kolekcja triggers kontrolki
Przykład użycia jako dodanie do kolekcji triggerów kontrolki:
Code:
<Button VerticalAlignment="Top" HorizontalAlignment="Left" Content="Przycisk"
Name="Button">
<Button.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:10" From="1" To="200" Storyboard.TargetName="Button" Storyboard.TargetProperty="Height" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
</Button>
Klasy akcji które możemy użyć w celu kontroli animacji:
- BeginStoryboard - służy do rozpoczynania animacji
- PauseStoryboard - zatrzymuje odtwarzanie animacji
- ResumeStoryboard - wznawia animację
- SeekStoryboard - szybkie przewinięcie do żądanego czasu
- SetStoryboardSpeedRatio - ustawia szybkość odtwarzania animacji
- SkipStoryboardToFill - przewija do końca animacji
- StopStoryboard - zatrzymuje odtwarzanie
Przykład poniższy pokazuje w jaki sposób zatrzymać animację:
Code:
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Name="stb1">
<Storyboard>
<DoubleAnimation Duration="0:0:5" Storyboard.TargetProperty="Height" To="200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<StopStoryboard BeginStoryboardName="stb1" />
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
Ważne, aby wszystkie akcje dla jednego StoryBoard były zawarte w jednej kolekcji StoryBoard. Jeżeli będą w różnych, funkcje nie będą wywoływane poprawnie.
Aby działanie SeekStoryboard mogło mieć miejsce, należy ustawić dla niej dwie dodatkowe właściwości:
- Orgin - może mieć wartość BeginTime lub Duration.
- Offset - o ile zostanie przewinięta animacja od momentu Orgin
Code:
<Style.Triggers>
<EventTrigger RoutedEvent="Button.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard Name="stb1">
<Storyboard>
<DoubleAnimation Duration="0:0:10" Storyboard.TargetProperty="Height" To="200" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Button.MouseLeave">
<EventTrigger.Actions>
<SeekStoryboard BeginStoryboardName="stb1" Origin="BeginTime" Offset="0:0:5" />
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
Powyższy przykład powoduje przewinięcie animacji 5 sekund od aktualnej pozycji.
Użycie property triggerów
Animację można także używać w przypadku property triggerów. Dostępne są w tym przypadku dwie kolekcje:
- EnterActions - akcje wykonywane w momencie zadziałania triggera
- ExitActions - uruchamiane w momencie gdy trigger staje się nieaktywny
Przykład:
Code:
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard Name="stb1">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="FontSize" To="20" Duration="0:0:.5" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="stb1" />
</Trigger.ExitActions>
</Trigger>
Klatkowe animacje
Jak wcześniej wspominałem ten rodzaj animacji definiuje serię klatek. Każda z nich posiada osobno definicję czasu trwania. Do dyspozycji mamy trzy rodzaje klatkowych animacji:
LinearDoubleKeyFrame - przejście między wartościami następuje w sposób jednostajny
Code:
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Height">
<LinearDoubleKeyFrame Value="10" KeyTime="0:0:1" />
<LinearDoubleKeyFrame Value="100" KeyTime="0:0:2" />
<LinearDoubleKeyFrame Value="30" KeyTime="0:0:4"/>
</DoubleAnimationUsingKeyFrames>
DiscreteStringKeyFrame - dla niektórych typów danych np. ciągów znakowych nie można zwiększyć wartości, dlatego stosuje się "dyskretne" zmiany, np:
Code:
<StringAnimationUsingKeyFrames Storyboard.TargetProperty="Content">
<DiscreteStringKeyFrame Value="Soup" KeyTime="0:0:0" />
<DiscreteStringKeyFrame Value="Sous" KeyTime="0:0:1" />
<DiscreteStringKeyFrame Value="Sots" KeyTime="0:0:2" />
<DiscreteStringKeyFrame Value="Nots" KeyTime="0:0:3" />
<DiscreteStringKeyFrame Value="Nuts" KeyTime="0:0:4" />
</StringAnimationUsingKeyFrames>
Spline key frames - zmiany są wyrażone przy użyciu krzywej Beziera:
Code:
<SplineDoubleKeyFrame Value="300" KeyTime="0:0:6" KeySpline="0.1,0.8 0.6,0.6" />