我有一个WPF应用程序,其中图像保持旋转,偶尔会有一些动画。应用程序播放时,旋转保持平稳运行,在两个关键帧保持相同值的时间内除之外。出于演示目的,我将其简化为最基本的要点:
<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>
该窗口包含一个图像元素,该图像元素具有RotateTransform作为其rendertransform,其旋转角度绑定到窗口代码隐藏中的属性。
还有一个动画,它会在第一秒内将图像的不透明度从0变为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;
}
属性类型为double的属性,包含RotateTransform的角度值。它使用INotifyPropertyChanged的事件处理程序来通知绑定的更改项。还有一个DispatcherTimer,每秒触发30次,每次滴答时它稍微增加Angle属性,使其保持旋转。
如果您运行该应用程序,您将发现图像以每秒1转的速度以30fps的速度旋转。它在第一秒内平滑地旋转和淡入,但是在不透明度保持为1的两秒期间,旋转变得非常不稳定。然后,当不透明度开始淡化回0时,旋转再次平滑。
奇怪的是,如果您确定不透明度不会保持在1,则可以修复此问题:如果您在这两秒内稍微增加它:
<SplineDoubleKeyFrame KeyTime="0:0:3" Value="1.001"/>
......旋转保持平稳。
这里发生了什么?
答案 0 :(得分:2)
DispatcherTimer
的默认优先级为Background
。此优先级描述如下:操作在所有其他非空闲操作完成后处理。
DoubleAnimationUsingKeyFrames
可能会优化掉重绘调用,因为不透明度不会发生变化,无论出于何种原因,这似乎会影响调度程序队列。
使用new DispatcherTimer(DispatcherPriority.Normal)
更改调度程序计时器优先级,或者实例化另一个DoubleAnimation
以设置角度动画,而不是手动设置动画。