2009-03-28 12 views
9

Sto usando una DoubleAnimation per anamizzare la proprietà Angle di un RotationTransform. Diverse volte al secondo, ho bisogno di cambiare la velocità della rotazione in risposta a dati esterni in modo che la rotazione acceleri e/o rallenti (senza intoppi) nel tempo. Attualmente sto facendo questo utilizzando un DoubleAnimation che si ripete sempre ,0-360,0 con la durata X, poi più volte al secondo:Modificare dinamicamente un'animazione di rotazione in WPF

  • Afferra un nuovo valore dai dati esterni
  • Modificare il tasso sui DoubleAnimation a quella valore
  • riapplicare il DoubleAnimation alla proprietà Angle nuovo

Nota: ho trovato che ho dovuto cambiare il da e per le proprietà sull'animazione a "angolo corrente" e "angolo corrente + 360" - Fortunatamente per me RotationTransform non ha problemi con gli angoli > 360 gradi - per evitare di riavviare la rotazione dall'angolo zero.

La mia domanda è: è ragionevole? Non sembra così. Applicare continuamente nuove DoubleAnimations alla proprietà Angle su una trasformazione di rotazione sembra errato, un po 'come se stessi permettendo a WPF di animare la rotazione, mentre I sto animando personalmente la velocità di rotazione.

C'è un modo migliore?

risposta

8

Nello storyboard è presente un'impostazione SpeedRatio che è un moltiplicatore della durata. Non è possibile associarlo a questo in quanto non è una proprietà di dipendenza.

Per aggirare questo problema è possibile utilizzare la funzione SetSpeedRatio sullo storyboard. Nota: funziona solo se la story board è stata avviata in codice (altrimenti si ottiene un errore).

Il codice seguente è un esempio completo di come si aumenterebbe l'evento in un oggetto per effettuare la velocità dell'animazione di un rettangolo rotante. Lo scopo della casella di testo e dei collegamenti dei dati è aggiornare l'oggetto di sfondo. Il pulsante è solo così la casella di testo perde lo stato attivo e aggiorna l'oggetto.

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <StackPanel> 
     <Rectangle Margin="50" Width="50" Height="50" Fill="Red" x:Name="rc"> 
     <Rectangle.RenderTransform> 
      <RotateTransform x:Name="TransRotate" 
          CenterX="25" CenterY="25" Angle="0" /> 
     </Rectangle.RenderTransform> 
     <Rectangle.Resources> 
      <Storyboard x:Key="spin"> 
      <DoubleAnimation x:Name="da" 
          Storyboard.TargetName="TransRotate" 
          Storyboard.TargetProperty="Angle" 
          By="360" 
          Duration="0:0:10" 
          AutoReverse="False" 
          RepeatBehavior="Forever" /> 
      </Storyboard> 
     </Rectangle.Resources> 
     </Rectangle> 
     <TextBox Text="{Binding Speed}" /> 
     <Button>Update Speed</Button> 
    </StackPanel> 
</Window> 

Poi il codice C#

{ 
    public Window1() 
    { 
     InitializeComponent(); 

     //create new object 
     BackgroundObject bo = new BackgroundObject(); 

     //binding only needed for the text box to change speed value 
     this.DataContext = bo; 

     //Hook up event 
     bo.SpeedChanged += bo_SpeedChanged; 

     //Needed to prevent an error 
     Storyboard sb = (Storyboard)rc.FindResource("spin"); 
     sb.Begin(); 
    } 

    //Change Speed 
    public void bo_SpeedChanged( object sender, int newSpeed) 
    { 
     Storyboard sb = (Storyboard)rc.FindResource("spin"); 
     sb.SetSpeedRatio(newSpeed); 
    } 
} 

public delegate void SpeedChangedEventHandler(object sender, int newSpeed); 

public class BackgroundObject 
{ 
    public BackgroundObject() 
    { 
     _speed = 10; 
    } 

    public event SpeedChangedEventHandler SpeedChanged; 

    private int _speed; 
    public int Speed 
    { 
     get { return _speed; } 
     set { _speed = value; SpeedChanged(this,value); } 
    } 
} 

Sono sicuro che si può adattare al vostro utilizzo.

+0

Questo sarebbe molto apprezzato. – Bill

+1

Grazie, sarò in grado di usarlo. È buffo che dobbiamo fare una chiamata al metodo (SetSpeedRatio), il che significa che non posso animare la variazione del rapporto di velocità con un'altra animazione, tutto in Xaml e tutto; ma questo sembra molto più corretto dell'applicazione di nuove animazioni in ogni momento per ottenere l'effetto. Grazie. – Bill

+0

Questa risposta è stata molto utile nel nostro caso, ma c'è una differenza importante che non ha funzionato. almeno con WPF in WinRT. Il metodo SetSpeedRatio() non ha fatto nulla, quindi lo abbiamo modificato con la proprietà SpeedRatio e questo ha fatto il trucco. –