2009-03-28 8 views
9

Używam funkcji DoubleAnimation do anamowania właściwości Angle obiektu RotationTransform. Kilka razy na sekundę muszę zmienić szybkość rotacji w odpowiedzi na dane zewnętrzne, tak aby obrót przyspieszył i/lub spowalniał (płynnie) z czasem. Jestem obecnie robi to za pomocą DoubleAnimation który powtarza się zawsze od 0,0 do 360,0 z czasem trwania X, a następnie kilka razy na sekundę:Dynamiczna zmiana animacji rotacji w programie WPF

  • porwać nowej wartości z danymi zewnętrznymi
  • Modyfikuj stawkę na DoubleAnimation temu wartość
  • ponownie ubiegać się DoubleAnimation do nieruchomości angle ponownie

Uwaga: znalazłem, że muszę zmienić do i od nieruchomości na animację „aktualny kąt” i „aktualny kąt + 360” - na szczęście dla mnie RotationTransform nie ma problemu z kątami > 360 stopni - aby zapobiec ponownemu uruchomieniu obracania od kąta zerowego.

Moje pytanie brzmi: czy to jest uzasadnione? Nie wydaje się tak. Ciągłe stosowanie nowych DoubleAnimations do właściwości Angle w transformacji rotacji wydaje się błędne - coś w rodzaju, że pozwalam WPF animować rotację, podczas gdy I animuję prędkość obrotową.

Czy istnieje lepszy sposób?

Odpowiedz

8

Na scenorysie znajduje się ustawienie SpeedRatio, które jest mnożnikiem czasu trwania. Nie można tego jednak powiązać, ponieważ nie jest to właściwość zależności.

Aby obejść ten problem, można użyć funkcji SetSpeedRatio w scenorysie. Zauważ, że działa to tylko wtedy, gdy tablica opowieści jest uruchamiana w kodzie (w innym przypadku pojawi się błąd).

Poniższy kod jest pełnym przykładem tego, jak podnosić wydarzenie w obiekcie, aby wpłynąć na szybkość animacji obracającego się prostokąta. Zadaniem pola tekstowego i powiązań danych jest aktualizacja obiektu tła. Przycisk jest po prostu taki, że pole tekstowe traci ostrość i aktualizuje obiekt.

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

Następnie kod 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); } 
    } 
} 

Jestem pewien, że można dostosować do użytkowania.

+0

To byłoby bardzo docenione. – Bill

+1

Dzięki, będę mógł z tego skorzystać. Zabawne, że musimy wykonać wywołanie metody (SetSpeedRatio), co oznacza, że ​​nie mogę animować zmiany stosunku prędkości z inną animacją, wszystko w Xaml i wszystkich; ale to wygląda o wiele bardziej poprawnie niż stosowanie nowych animacji przez cały czas, aby uzyskać efekt. Dziękuję. – Bill

+0

Ta odpowiedź była najbardziej przydatna w naszym przypadku, ale jest jedna ważna różnica, która nie sprawdziła jej. przynajmniej z WPF w WinRT. Metoda SetSpeedRatio() nie zrobiła nic, więc zmieniliśmy ją na właściwość SpeedRatio i to wystarczyło. –