Animazione di un oggetto con traiettoria ellittica in Silverlight 2.0
di Alessio Leoncini, in Silverlight 2.0, il 12 marzo 2009 alle 08:00
Archiviato in: Silverlight, Silverlight - animazioni, Silverlight 2.0, Windows Presentation Foundation, XAML
Commenti
mi piace (0)
non mi piace (0) Silverlight dispone di molti oggetti per la realizzazione di animazioni, il namespace System.Windows.Media.Animation espone una serie di classi ben progettate, ognuna di esse orientata all'interpolazione lineare e non di specifiche proprietà nel tempo, mettendo a disposizione strumenti molto flessibili per l'implementazione di svariati effetti animati.
Qualora ce ne sia necessità è possibile utilizzare l'oggetto Storyboard come timer ciclico per il calcolo manuale dei valori degli oggetti da assegnare nel tempo; con questa modalità si possono coprire quegli scenari in cui la semplice interpolazione non è sufficiente ed andare a realizzare animazioni ancora più ricche.
In questo script è illustrata la possibilità di animare lo spostamento di un oggetto seguendo una traiettoria ellittica anzichè rettilinea, l'implementazione è molto semplice e si basa sull'uso della trigonometria per il calcolo istante per istante della posizione dell'oggetto in funzione dell'angolo di rotazione.
Il primo aspetto importante è posizionare l'oggetto da animare all'interno di un Canvas in modo da avere completo controllo sul suo posizionamento assoluto:
<UserControl x:Class="_40.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="800" Height="600"> <Canvas x:Name="LayoutRoot"> <Ellipse x:Name="Ellipse1" Height="50" Width="50" Fill="Red"></Ellipse> </Canvas> </UserControl>
public partial class Page : UserControl { //Storyboard da utilizzare come timer Storyboard _anim = new Storyboard(); //centro dell'applicazione Point _center = new Point(); //velocità dell'oggetto double _speed = 0.02; //angolo di partenza double _angleCurrent = -0.5; //angolo di destinazione double _angleEnd = 2.75; //raggio orizzontale dell'arco double _radiusX = 200; //raggio verticale dell'arco double _radiusY = 100; public Page() { InitializeComponent(); //calcolo centro dell'applicazione _center.X = (this.Width / 2); _center.Y = (this.Height / 2); //posizionamento iniziale dell'oggetto da animare Ellipse1.SetValue(Canvas.LeftProperty, _center.X); Ellipse1.SetValue(Canvas.TopProperty, _center.Y); //animazione timer _anim.Duration = new Duration(TimeSpan.FromMilliseconds(10)); _anim.Completed += new EventHandler(_anim_Completed); _anim.Begin(); }
Nella classe vengono dichiarate alcune varibili per l'animazione, _radiusX e _radiusY definiscono l'ampiezza dell'ellisse attraverso due raggi; nel costruttore l'oggetto Storyboard _anim imposta la cadenza con cui vengono ricalcolati i valori attraverso il metodo _anim_Completed che viene eseguito ogni 10 millisecondi:
void _anim_Completed(object sender, EventArgs e) { //controllo angolo di rotazione if (_angleCurrent <= _angleEnd) { //calcolo posizione sull'arco double _newX = _center.X + (Math.Cos(_angleCurrent) * _radiusX); double _newY = _center.Y + (Math.Sin(_angleCurrent) * _radiusY); //posizionamento dell'oggetto Ellipse1.SetValue(Canvas.LeftProperty, _newX - (Ellipse1.Width / 2)); Ellipse1.SetValue(Canvas.TopProperty, _newY - (Ellipse1.Height / 2)); //tracciatura per visione della traiettoria Line _line1 = new Line(); _line1.Stroke = new SolidColorBrush(Color.FromArgb(100, 50, 50, 50)); _line1.StrokeThickness = 1; _line1.X1 = _newX; _line1.Y1 = _newY; _line1.X2 = _newX + 1; _line1.Y2 = _newY + 1; LayoutRoot.Children.Add(_line1); //variazione dell'angolo in funzione della velocità desiderata _angleCurrent = _angleCurrent + _speed; _anim.Begin(); } }






