Динамично променяйте ротационна анимация в WPF

Използвам DoubleAnimation за анамизиране на свойството Angle на RotationTransform. Няколко пъти в секунда трябва да променя скоростта на въртене в отговор на външни данни, така че въртенето да се ускорява и/или забавя (плавно) с течение на времето. В момента правя това, като използвам DoubleAnimation, който се повтаря завинаги от 0.0 до 360.0 с продължителност X, след това няколко пъти в секунда:

  • Вземете нова стойност от външни данни
  • Променете скоростта на DoubleAnimation до тази стойност
  • Приложете отново DoubleAnimation към свойството Angle отново

Забележка: Наистина открих, че трябваше да променя свойствата До и От на анимацията на „текущ ъгъл“ и „текущ ъгъл+360“ – за мое щастие RotationTransform няма проблеми с ъгли > 360 градуса – за да предотврати стартирането на въртенето отгоре отново от нулев ъгъл.

Въпросът ми е: това разумно ли е? Не изглежда така. Непрекъснатото прилагане на нови DoubleAnimations към свойството Angle при трансформация на въртене изглежда погрешно - нещо като оставям на WPF да анимира въртенето, докато Аз сам анимирам скоростта на въртене.

Има ли по-добър начин?


person Bill    schedule 28.03.2009    source източник


Отговори (1)


В разкадровката има настройка SpeedRatio, която е множител на продължителността. Не можете да се обвържете с това обаче, тъй като не е свойство на зависимост.

За да заобиколите това, можете да използвате функцията SetSpeedRatio в сценария. Имайте предвид, че това работи само ако бордът с истории е стартиран в код (в противен случай получавате грешка).

Кодът по-долу е пълен пример за това как бихте повдигнали събитие в обект, за да повлияете на скоростта на анимацията на въртящ се правоъгълник. Целта на текстовото поле и обвързването на данни е да актуализира фоновия обект. Бутонът е точно така, че текстовото поле да губи фокуса и да актуализира обекта.

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

След това 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); }
    }
}

Сигурен съм, че можете да се адаптирате към вашата употреба.

person John    schedule 28.03.2009
comment
Това ще бъде много оценено. - person Bill; 28.03.2009
comment
Благодаря, ще мога да го използвам. Странно, че трябва да направим извикване на метод (SetSpeedRatio), което означава, че не мога да анимирам промяната на съотношението на скоростта с друга анимация, всичко в Xaml и всички; но това изглежда много по-правилно от прилагането на нови анимации през цялото време, за да получите ефекта. Благодаря ти. - person Bill; 28.03.2009
comment
Този отговор беше най-полезен в нашия случай, но има една важна разлика, която не го накара да работи. поне с WPF в WinRT. Методът SetSpeedRatio() не направи нищо, така че го променихме на свойството SpeedRatio и това свърши работа. - person Johan B; 13.12.2013