2009-03-28 8 views
9

Ich verwende eine DoubleAnimation, um die Angle-Eigenschaft einer RotationTransform zu antizipieren. Einige Male pro Sekunde muss ich die Rotationsrate als Antwort auf externe Daten ändern, so dass die Rotation im Laufe der Zeit beschleunigt und/oder verlangsamt wird. Ich tue dies derzeit durch einen Double verwenden, die für immer mit der Dauer X ,0-360,0 wiederholt, dann mehrmals pro Sekunde:Dynamische Änderung einer Rotationsanimation in WPF

  • Ergreifen Sie einen neuen Wert von externen Daten
  • Ändern Sie die Rate auf dem Double zu, dass Wert
  • Re-übernehmen Sie die Double auf die Winkeleigenschaft wieder

Hinweis: ich fand, dass ich das ändern musste und von Eigenschaften auf der Animation auf den „aktuelle Winkel“ und „Stromwinkel + 360“ - Glück für mich RotationTransform hat keine Probleme mit Winkeln > 360 Grad - um ein erneutes Starten der Drehung aus dem Nullwinkel zu verhindern.

Meine Frage ist: Ist das vernünftig? Es scheint nicht so. Kontinuierliches Anwenden neuer DoubleAnimations auf die Angle-Eigenschaft bei einer Rotationstransformation scheint falsch zu sein - so wie ich WPF die Rotation animieren lasse, während I die Rotationsgeschwindigkeit selbst animiert.

Gibt es einen besseren Weg?

Antwort

8

Auf dem Storyboard gibt es eine SpeedRatio-Einstellung, die ein Multiplikator für die Dauer ist. Sie können dies jedoch nicht binden, da es keine Abhängigkeitseigenschaft ist.

Um dies zu umgehen, können Sie die Funktion SetSpeedRatio auf dem Storyboard verwenden. Beachten Sie, dass dies nur funktioniert, wenn das Storyboard im Code gestartet wird (andernfalls erhalten Sie einen Fehler).

Der folgende Code ist ein vollständiges Beispiel dafür, wie Sie ein Ereignis in einem Objekt auslösen würden, um die Geschwindigkeit der Animation eines sich drehenden Rechtecks ​​zu beeinflussen. Der Zweck der Textbox und der Datenbindungen besteht darin, das Hintergrundobjekt zu aktualisieren. Die Schaltfläche ist nur so, dass die Textbox den Fokus verliert und das Objekt aktualisiert.

<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> 

Dann wird der C# -Code

{ 
    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); } 
    } 
} 

Ich bin sicher, dass Sie Ihre Nutzung anpassen können.

+0

Das würde sehr geschätzt werden. – Bill

+1

Danke, ich werde das nutzen können. Komisch, dass wir einen Methodenaufruf machen müssen (SetSpeedRatio), was bedeutet, dass ich die Geschwindigkeitsverhältnisänderung nicht mit einer anderen Animation animieren kann, alles in Xaml und allen; aber das sieht viel korrekter aus als neue Animationen die ganze Zeit anzuwenden, um den Effekt zu erzielen. Danke. – Bill

+0

Diese Antwort war in unserem Fall am nützlichsten, aber es gibt einen wichtigen Unterschied, der es nicht funktionierte. zumindest mit WPF in WinRT. Die Methode SetSpeedRatio() hat nichts gemacht, also haben wir sie in die Eigenschaft SpeedRatio geändert und das hat den Trick gemacht. –