Динамическое изменение анимации вращения в WPF
Я использую DoubleAnimation для анализа свойства угла RotationTransform. Несколько раз в секунду, мне нужно изменить скорость вращения в ответ на внешние данные, так что скорость вращения и/или тормозит (плавно) с течением времени. В настоящее время я делаю это, используя DoubleAnimation, который повторяется навсегда от 0.0 до 360,0 с длительностью X, а затем несколько раз в секунду:
- возьмите новое значение из внешних данных
- изменить тариф на удвоение к этому значению
- повторно примените свойство DoubleAnimation к свойству Angle еще раз
Примечание: я обнаружил, что мне пришлось изменить свойства To и From анимации на "текущий угол" и "текущий угол+360" - к счастью для меня RotationTransform не имеет проблем с углами > 360 градусов - чтобы предотвратить запуск вращения снова с нулевого угла.
мой вопрос: это разумно? Это, кажется, не так. Непрерывное применение новых DoubleAnimations к свойству Angle на преобразовании вращения кажется неправильным - вроде как я позволяю WPF анимировать вращение, в то время как Я я сам анимирую скорость вращения.
есть ли лучший способ?
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); }
}
}
Я уверен, что вы можете адаптироваться к вашему использованию.