10

我正在使用 DoubleAnimation 对 RotationTransform 的 Angle 属性进行动画处理。每秒几次,我需要更改旋转速率以响应外部数据,以便随着时间的推移旋转加快和/或减慢(平稳)。我目前正在通过使用从 0.0 到 360.0 以持续时间 X 永远重复的 DoubleAnimation 来执行此操作,然后每秒重复几次:

  • 从外部数据中获取新价值
  • 将 DoubleAnimation 上的速率修改为该值
  • 再次将 DoubleAnimation 重新应用到 Angle 属性

注意:我确实发现我必须将动画上的 To 和 From 属性更改为“当前角度”和“当前角度+360”——幸运的是,RotationTransform 在角度 > 360 度时没有问题——以防止开始旋转再次从零角度。

我的问题是:这合理吗?似乎并非如此。不断地将新的 DoubleAnimations 应用于旋转变换的 Angle 属性似乎是错误的 - 有点像我让 WPF 为旋转设置动画,而自己在为旋转速度设置动画。

有没有更好的办法?

4

1 回答 1

10

在故事板上有一个 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); }
    }
}

我相信你可以适应你的使用。

于 2009-03-28T15:08:18.217 回答