我有一个
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;
}
有一个属性Angle类型double,包含RotateTransform的角度值.它使用INotifyPropertyChanged的事件处理程序来通知绑定的更改项.还有一个DispatcherTimer每秒触发30次,并且在每个刻度上它稍微增加了Angle属性,以便它保持旋转.
如果运行该应用程序,您会发现图像以每秒1转的速度以30fps的速度旋转.它在第一秒内平滑地旋转和淡入,但是在不透明度保持为1的两秒期间,旋转变得非常不稳定.然后,当不透明度开始渐渐变回0时,旋转再次平滑.
奇怪的是,如果您确定不透明度不会保持在1,则可以修复此问题:如果您在这两秒内稍微增加它:
<SplineDoubleKeyFrame KeyTime="0:0:3" Value="1.001"/>
……旋转保持平稳.
这里发生了什么?
最佳答案 DispatcherTimer的默认优先级是Background.该优先级描述如下:在完成所有其他非空闲操作之后处理操作.
DoubleAnimationUsingKeyFrames可能会优化掉重绘调用,因为不透明度没有改变,并且无论出于何种原因,这似乎会影响调度程序队列.
使用新的DispatcherTimer(DispatcherPriority.Normal)更改调度程序计时器优先级,或者实例化另一个DoubleAnimation以设置角度动画,而不是手动设置动画.