4

画像が回転し続ける WPF アプリケーションがあり、場合によっては何らかのアニメーションが表示されます。2 つのキーフレームが同じ値を保持している場合を除いて、アプリケーションの再生時に回転はスムーズに実行され続けます。デモンストレーションの目的で、私はそれを必要最小限に絞り込みました:

<Window x:Class="WpfApplication3.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525"
    x:Name="RootElement">
<Window.Resources>

    <Storyboard x:Key="Storyboard1">
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="image">
            <SplineDoubleKeyFrame KeyTime="0" Value="0"/>
            <SplineDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
            <SplineDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
            <SplineDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>

</Window.Resources>
<Window.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
    </EventTrigger>
</Window.Triggers>
<Grid>
    <Image x:Name="image" Source="image.jpg" RenderTransformOrigin="0.5,0.5" >
        <Image.RenderTransform>
            <RotateTransform Angle="{Binding Angle, ElementName=RootElement}" />
        </Image.RenderTransform>
    </Image>
</Grid>

ウィンドウには、rendertransform として RotateTransform を持つイメージ要素が含まれており、回転の角度はウィンドウの分離コードのプロパティにバインドされています。

画像の不透明度を最初の 1 秒間で 0 から 1 にフェードインし、次の 2 秒間は 1 に保持し、最後の 1 秒間で 1 から 0 にフェードするアニメーションもあります。

コードビハインドは次のようになります。

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();

        timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromSeconds(1.0 / 30.0);
        timer.Tick += timer_Tick;
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        Angle += 360.0 * timer.Interval.TotalSeconds;
    }

    private DispatcherTimer timer;
    private double angle;

    public double Angle
    {
        get { return angle; }
        set 
        { 
            angle = value; 

            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Angle"));
            }
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
}

RotateTransform の角度値を含む double 型のプロパティ Angle があります。INotifyPropertyChanged のイベント ハンドラーを使用して、バインドされたアイテムに変更を通知します。また、1 秒間に 30 回起動する DispatcherTimer もあり、ティックごとに Angle プロパティがわずかに増加し、回転し続けるようになっています。

アプリケーションを実行すると、画像が 30 fps で毎秒 1 回転の速度で回転することがわかります。回転して最初の 1 秒間はスムーズにフェード インしますが、不透明度が 1 のままである 2 秒間は、回転が途切れ途切れになります。その後、不透明度がフェードして 0 に戻ると、回転は再びスムーズになります。

奇妙なことに、不透明度が 1 のままにならないようにすれば、これを修正できます。

<SplineDoubleKeyFrame KeyTime="0:0:3" Value="1.001"/>

...回転は滑らかなままです。

ここで何が起こっているのですか?

4

1 に答える 1

2

のデフォルトのプライオリティはDispatcherTimerですBackground。この優先順位は、次のように説明されています。操作は、他のすべての非アイドル操作が完了した後に処理されます。

不透明度が変化していないため、再描画呼び出しを最適化するDoubleAnimationUsingKeyFrames可能性が高く、何らかの理由でこれがディスパッチャー キューに影響を与えるようです。

ディスパッチャ タイマーの優先度を変更するか、new DispatcherTimer(DispatcherPriority.Normal)別のインスタンスを作成DoubleAnimationして、手動でアニメートするのではなく角度をアニメートします。

于 2014-07-28T12:12:42.217 に答える