C# 在 WPF 中动态更改旋转动画
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/692634/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Dynamically Change a Rotation Animation in WPF
提问by Bill
I am using a DoubleAnimation to anamiate the Angle property of a RotationTransform. Several times per second, I need to change the rate of the rotation in response to external data so that the rotation speeds up and/or slows down (smoothly) over time. I am currently doing this by using a DoubleAnimation that repeats forever from 0.0 to 360.0 with duration X, then several times per second:
我正在使用 DoubleAnimation 来分析 RotationTransform 的 Angle 属性。每秒数次,我需要根据外部数据更改旋转速率,以便随着时间的推移旋转加速和/或减速(平稳)。我目前正在通过使用一个 DoubleAnimation 来做到这一点,它从 0.0 到 360.0 永远重复,持续时间为 X,然后每秒多次:
- Grab a new value from external data
- Modify the rate on the DoubleAnimation to that value
- Re-Apply the DoubleAnimation to the Angle property again
- 从外部数据中获取新值
- 将 DoubleAnimation 的速率修改为该值
- 再次将 DoubleAnimation 重新应用于 Angle 属性
Note: I did find that I had to change the To and From properties on the animation to "current angle" and "current angle+360" - lucky for me RotationTransform has no trouble with angles > 360 degrees - to prevent starting the rotation over again from zero angle.
注意:我确实发现我必须将动画上的 To 和 From 属性更改为“当前角度”和“当前角度+360” - 对我来说幸运的是 RotationTransform 在角度 > 360 度时没有问题 - 以防止开始旋转再次从零角度。
My question is: Is this reasonable? It does not seem so. Continously applying new DoubleAnimations to the Angle property on a rotation transform seems wrong - sort of like I am letting WPF animate the rotation, while Iam animating the rotation speed myself.
我的问题是:这合理吗?似乎并非如此。连续将新的 DoubleAnimations 应用到旋转变换上的 Angle 属性似乎是错误的 - 有点像我让 WPF 为旋转设置动画,而我自己正在为旋转速度设置动画。
Is there a better way?
有没有更好的办法?
采纳答案by John
On the storyboard there is a SpeedRatio setting which is a multiplier to the duration. You cannot bind to this however as it is not a dependency property.
在故事板上有一个 SpeedRatio 设置,它是持续时间的乘数。但是,您不能绑定到 this,因为它不是依赖属性。
To get around this you can use the SetSpeedRatio function on the storyboard. Note this only works if the story board is started in code (other wise you get an error).
为了解决这个问题,您可以使用情节提要上的 SetSpeedRatio 函数。请注意,这仅在故事板以代码启动时才有效(否则会出现错误)。
The code below is an full example of how you would raise event in an object to effect the speed of the animation of a spinning rectangle. The purpose of the textbox and data bindings are to update the background object. The button is just so the textbox looses focus and updates the object.
下面的代码是如何在对象中引发事件以影响旋转矩形动画速度的完整示例。文本框和数据绑定的目的是更新背景对象。该按钮只是使文本框失去焦点并更新对象。
<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>
Then the C# code
然后是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); }
}
}
I am sure you can adapt to your usage.
我相信你可以适应你的使用。