Come la maggior parte di coloro che per la prima volta si avvicinano a WPF mi sono trovato a gestire le animazioni attraverso le Timeline.
Un animazione gradevole e didatticamente interessante consiste nel far ingrandire un oggetto qualsiasi (button, image, o qualsiasi altro) al passaggio del mouse.
Ottenere quest’effetto è molto semplice, basta andare a modificare i valori dei due moltiplicatori X e Y (scale orizzontale e scale verticale). Di default entrambi i valori sono impostati a 1, che è come dire 100%
Cosa significa questo: che se il nostro button (ad esempio) è alto 10 pixel, con il valore di scale Y a 1, diventa 10 x 1 = 10 pixel quindi dimensione originale. Modificando il moltiplicatore e impostandolo a 2 (200%), è banalmente ovvio che il nostro button diventerà alto 20.
Torniamo a noi. Volendo creare un animazione, che al passaggio del mouse ingrandisca il nostro oggetto raddoppiandone le dimensioni, ci basta agganciarne l’evento OnMouseEnter e, impostando nella timeline un arco di tempo a piacere (diciamo mezzo secondo) e successivamente cambiare i valori, da 1 a 2, dei campi X e Y nel campo scale del LayoutTransform .
Volendo fare l’operazione opposta, e cioè agganciando all’oggetto l’evento OnMouseLeave per far si che all’uscita del mouse, il nostro oggetto torni alle dimensioni originali, ho incontrato un problema. Ho ovviamente creato una nuova timeline, impostato lo scale a 2 del LayoutTransform per indicare, ovviamente, i valori di inizio interpolazione, e poi, a mezzo secondo di distanza nella timeline, ho impostato di nuovo i valori dello scale a 1.
[code language="xml"]
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="prova" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="2"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="prova" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="2"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
[/code]
Mandando in esecuzione l’applicazione, dopo pochissime prove, ho notato un insolito e alquanto poco gradito comportamento: facendo uscire il mouse dal mio oggetto prima del termine dell’animazione (in pratica scatenando l’evento OnMouseLeave quando il mio oggetto non era ancora completamente ingrandito), questo “scattava” alla dimensione raddoppiata per poi proseguire correttamente con la seconda animazione e quindi tornando fluidamente alle dimensioni originali.
Facendo un paio di prove ho scoperto che la cosa è di una semplicità disarmante ma, soprattutto per chi come me ha avuto già a che fare in precedenza con animazioni, timeline e interpolatori vari, non molto ovvia.
L’errore da me commesso è stato di settare lo scale a 2 per indicare i valori di inizio interpolazione per l’animazione di “restringimento”. Non impostandoli, ma impostando solo i valori di fine interpolazione, WPF fa partire l’interpolazione dai valori attuali dello scale, qualsiasi essi siano.
[code language="xml"]
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="prova" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="prova" Storyboard.TargetProperty="(FrameworkElement.LayoutTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)">
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
[/code]
Lanciando la nostra applicazione, possiamo vedere che, l’effetto voluto è gradevole e fluido.
Sperando di avervi risparmiato quei 5 minuti di prove, saluto tutti.