10

RotationTransform の Angle プロパティをアニメーション化するために DoubleAnimation を使用しています。1 秒間に数回、外部データに応じて回転速度を変更して、時間の経過とともに回転が (スムーズに) 加速または減速するようにする必要があります。私は現在、0.0 から 360.0 まで持続時間 X で永遠に繰り返す DoubleAnimation を使用してこれを行っています。

  • 外部データから新しい価値をつかむ
  • DoubleAnimation のレートをその値に変更します
  • DoubleAnimation を Angle プロパティに再度適用します。

注: アニメーションの To および From プロパティを「現在の角度」および「現在の角度 + 360」に変更する必要があることがわかりました。幸運なことに、RotationTransform は 360 度を超える角度で問題がありません。回転が開始されないようにするためです。再びゼロアングルから。

私の質問は次のとおりです。これは合理的ですか?そうではないようです。回転変換のAngleプロパティに新しいDoubleAnimationsを継続的に適用すると、間違っているように見えます-回転速度を自分でアニメーション化している間に、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 に答える