È possibile pensare ad un'animazione Silverlight come alla modifica delle caratteristiche di un elemento di una pagina. Ad esempio, immaginiamo un testo che appaia in una determinata posizione in un certo momento, o che segua un percorso lungo la pagina, o cambi colore. Le stesse trasformazioni possiamo applicarle alle immagini o a forme geometriche.
Per realizzare l'animazione ci serviamo di elementi grafici XAML e di metodi e proprietà che ci permettono di gestire gli eventi con JavaScript.
Supponiamo, ad esempio, di voler animare un blocco di testo, facendo sì che scorra in orizzontale, per un tempo prefissato,da una posizione a un'altra.
Anzitutto creiamo l'elemento da animare:
<TextBlock x:Name="Animazione" Text="Animazione orizzontale"
Canvas.Left="10" Canvas.Top="10"
FontFamily="Times New Roman" FontSize="24" Foreground="Black">
</TextBlock>
Il blocco di testo, che abbiamo nominato "Animazione" (attributo x:Name
), si trova inizialmente alla posizione (10,10)
rispetto all'angolo in alto a sinistra del suo contenitore. Ne abbiamo impostato font e dimensioni del carattere e colore.
Il nome è molto importante, perché offre un riferimento all'elemento nel codice (un po' come l'id nell'XHTML)
Una volta definito il blocco di testo, possiamo impostare alcune azioni che l'oggetto effettuerà allo scatenarsi di alcuni eventi.
L'idea è che ciascun oggetto può reagire ad alcuni "stimoli" (trigger). Gli stimoli sono eventi elencati in un elemento particolare: l'elemento <TextBlock.Triggers>
. Nella collezione dei trigger possiamo definire gli eventi come altrettanti elementi <Event Trigger>
.
Ad esempio vediamo come assegnare un'azione al blocco di testo che si scatena quando è completo il caricamento.
<TextBlock x:Name="Animazione" Text="Animazione orizzontale"
Canvas.Left="10" Canvas.Top="10"
FontFamily="Times New Roman" FontSize="24" Foreground="Black">
<TextBlock.Triggers>
<Event Trigger RoutedEvent="TextBlock.Loaded">
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
L'evento destinato ad avviare l'animazione è TextBlock.Loaded
.
Lo Storyboard
A questo punto possiamo passare a definire l'azione. Si tratta di descrivere una vera e propria "storia", ovvero la sequenza di operazioni da effettuare.
Per modificare progressivamente la posizione orizzontale (Canvas.Left
) del blocco di testo utilizziamo l'elemento <DoubleAnimation>
, che incrementa un valore di tipo Double
a partire da un valore iniziale fino ad un valore finale.
Scegliendo come valore la distanza dal margine sinistro del blocco di testo, si otterrà che il blocco di testo stesso, una volta caricato, scorra verso destra.
<TextBlock x:Name="Animazione" Text="Animazione orizzontale" Canvas.Left="10" Canvas.Top="10" FontFamily="Times New Roman" FontSize="24" Foreground="Black"> <TextBlock.Triggers> <Event Trigger RoutedEvent="TextBlock.Loaded"> <BeginStoryboard> <Storyboard> <DoubleAnimation From= "10" To= "200" Storyboard.TargetName= "Animazione" Storyboard.TargetProperty= "Canvas.Left" /> </Storyboard> </BeginStoryboard> </EventTrigger> </TextBlock.Triggers> </TextBlock>
Riepilogando, le animazioni vengono definite all'interno di tag <BeginStoryboard>
e <Storyboard>
, nel tag <Storyboard>
indichiamo le azioni come <DoubleAnimation>
.
Proprietà e comportamenti
Nell'esempio abbiamo utilizzato <DoubleAnimation>
per rendere variabile nel tempo, a partire dall'istante successivo al caricamento, la distanza dal margine sinistro (Canvas.Left
) dell'oggetto Animazione
(Storyboard.TargetName= "Animazione"
) a partire dal valore 10
fino al valore 200
(From="10" To="200"
).
Abbiamo stabilito l'azione che il blocco di testo effettuerà. Ma la definizione di una certa azione, ad esempio <DoubleAnimation>
può essere arricchita servendosi di ulteriori proprietà. Esaminiamone alcune rapidamente.
La proprietà Duration ci permette di specificare la durata dell'animazione (nel formato hh:mm:ss
).
La proprietà AutoReverse, fa sì che, una volta conclusa l'animazione l'effetto venga annullato. Nel nostro caso la scritta, dopo aver percorso i 200 pixel, tornerebbe al punto di partenza.
Con RepeatBehavior possiamo impostare la ripetizione dell'animazione per il numero di volte che desideriamo, e, oltre al numero di ripetizioni, sarà possibile specificare la durata complessiva dell'animazione. Con l'attibuto Forever
possiamo far continuare la ripetizione in un ciclo infinito.
Nel caso di più animazioni successive, specialmente se riferite allo stesso oggetto e dunque comprese all'interno dello stesso Storyboard
assume particolare importanza anche la proprietà BeginTime. Con questa proprietà è possibile definire l'istante in cui l'animazione ha luogo, identificandolo come la distanza temporale (in secondi) rispetto all'evento che ha attivato l'animazione (in genere la conclusione del processo di caricamento dell'elemento in oggetto). Nel caso di animazioni successive sullo stesso oggetto, ad esempio un blocco di testo che scorre prima verso destra e poi verso il basso, è necessario prestare attenzione: nell'esempio di cui sopra il valore di BeginTime
della seconda animazione dovrebbe essere equivalente al valore di Duration
del primo, in modo da garantire un'effettiva consequenzialità degli eventi, senza sovrapposizioni.
Anche se molto usato, il tag <DoubleAnimation>
non è l'unico dedicato ad effetti di animazione. Tra gli altri, ad esempio, <ColorAnimation> e <PointAnimation>.
Tramite il tag <ColorAnimation> si possono animare le proprietà di colore di un oggetto, ad esempio modificando la proprietà Stroke
di un Rettangolo e facendo sì che il colore del bordo cambi da rosso a blu. In questo caso definiamo, nello Storyboard, una <ColorAnimation>
in modo simile a quantto visto per <DoubleAnimation>
, ma con diversi valori associati agli attributi From
e To
(in questo caso inseriamo "Red" e "Blue", rispettivamente). Dopo aver definito, così come nell'esempio precedentemente esaminato, il nome dell'animazione (Provarettangolo
) e la proprietà da animare (Color
) sarà sufficiente inserire un riferimento all'interno della propreità SolidColorBrush
definita nel del tag <Rectangle.Stroke>
.
<Rectangle.Stroke> <SolidColorBrush x:Name= "Provarettangolo"/> </Rectangle.Stroke>
Analogamente, utilizzando <PointAnimation>
, le animazioni potranno essere riferite non a valori numerici o a colori, ma a punti.
Per i tipi di animazione presi in esame finora, possiamo definire solo un valore iniziale, un valore finale e un intervallo di tempo in cui passare dall'uno all'altro, senza specificare l'andamento della variazione. Questo livello di dettaglio può essere raggiunto grazie all'utilizzo dei KeyFrame, dunque trasformando i tag precedentemente esaminati in <DoubleAnimationUsingKeyFrames>
, <ColorAnimationUsingKeyFrames>
e <PointAnimationUsingKeyFrames>
.
Potremo definire andamenti di tipo lineare, discreto o di tipo Spline (cioè secondo l'andamento di una curva di Bèzier i cui punti di controllo vanno passati come parametri).
<DoubleAnimationUsingKeyFrames Duration="0:0:4.5" Storyboard.TargetName="myTranslate" Storyboard.TargetProperty="Y" RepeatBehavior="Forever"> <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0" /> <SplineDoubleKeyFrame Value="375" KeyTime="0:0:2.2" KeySpline="0, 0, 0.5, 0" /> <LinearDoubleKeyFrame Value="375" KeyTime="0:0:2.25" /> <SplineDoubleKeyFrame Value="0" KeyTime="0:0:4.5" KeySpline="0, 0, 0, 0.5" /> </DoubleAnimationUsingKeyFrames>
Interazione con i linguaggi di scripting
Per l'integrazione con le animazioni tramite scripting (JavaScript ad esempio), possiamo utilizzare i metodi esposti dalla classe Storyboard
:
begin()
: avvia l'animazionepause()
: mette l'animazione in pausaresume()
: fa proseguire un'animazione precedentemente messa in pausastop()
: blocca l'animazioneseek(int sec)
: stabilisce il punto iniziale in secondi, rispetto all'istante di avvio