【问题标题】:Dynamically Change a Rotation Animation in WPF在 WPF 中动态更改旋转动画
【发布时间】:2010-10-16 02:40:41
【问题描述】:

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

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

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

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

有没有更好的办法?

【问题讨论】:

    标签: c# wpf xaml animation transform


    【解决方案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); }
        }
    }
    

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

    【讨论】:

    • 非常感谢。
    • 谢谢,我可以使用它。有趣的是,我们必须进行方法调用 (SetSpeedRatio),这意味着我不能用另一个动画来动画速度比的变化,所有这些都在 Xaml 中;但这看起来比一直应用新动画来获得效果要正确得多。谢谢。
    • 这个答案在我们的案例中是最有用的,但是有一个重要的区别没有让它起作用。至少在 WinRT 中使用 WPF。方法 SetSpeedRatio() 没有做任何事情,因此我们将其更改为属性 SpeedRatio 并且成功了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多