我正在努力平滑WPF动画
其实我的动画代码如下:
private void AnimateX ( FrameworkElement element, double XMoveStart, double XMoveEnd, int secondX)
{
SineEase eEase = new SineEase();
eEase.EasingMode = EasingMode.EaseInOut;
Storyboard sb = new Storyboard();
DoubleAnimation daX = new DoubleAnimation(XMoveStart, XMoveEnd, new Duration(new TimeSpan(0, 0, 0, secondX, 0)));
daX.EasingFunction = eEase;
Storyboard.SetTargetProperty(daX, new PropertyPath("(Canvas.Left)"));
sb.Children.Add(daX);
element.BeginStoryboard(sb);
}
上面的代码是一种以正弦方式水平移动对象的方法。当只有一个物体在移动时,就可以了。但是,每当两个或多个对象一起移动时(在前一个动画尚未完成时在另一个对象上调用AnimateX方法),动画就会开始变得紧张。我的意思是,在动画过程中,物体会发抖。
答案 0 :(得分:1)
我多次遇到同样的问题。我发现根据你添加到画布的对象,WPF通常必须在每个帧上重新生成这些对象的表示(我认为可能是你的情况,这取决于你正在操作的UI元素的类型)。您可以通过告诉WPF在位图中缓存画布的表示来解决抖动问题。在画布的Xaml定义中,这很简单,如下所示:
<Canvas ...Your canvas properties...>
<Canvas.CacheMode>
<BitmapCache />
</Canvas.CacheMode>
...Your objects...
</Canvas>`
这减少了WPF应用程序的负载,因为它只是将对象的表示形式存储为位图图像,因此您的应用程序不必在每个帧上重绘它们。此解决方案仅在您的动画外部应用于画布时才有效,并且没有正在进行的局部动画应用于画布中绘制的各个对象。如果代码中的其他动画将两个对象相互移动,您将希望创建具有自己的缓存的分隔画布。
请注意,此策略不会放宽某些UI元素。但是,我已经看到这种策略可以有效地用于许多元素,包括 TextBoxes 等等,以及几何形状。无论如何,总是值得一试。
其次,如果缓存本地表示不够,那么您可能希望查看代码的性能,并查看是否有任何进程可能会暂时阻止UI。关于这方面没有统一的解决方案,这取决于还有什么对您的应用程序UI造成压力。清理代码并使用相关的异步流程可以提供帮助。
最后,如果在所有这些检查之后,对您的应用程序的整体需求仍然太高,您可以通过降低其一般帧速率,默认为60来稍微消除应用程序上的一些压力。您可以尝试30或40并查看如果这通过在初始化中包含以下代码来改善抖动:
Timeline.DesiredFrameRateProperty.OverrideMetadata(typeof(Timeline), new FrameworkPropertyMetadata { DefaultValue = 40 });
答案 1 :(得分:0)
只是一个猜测,但如果您直接为该属性设置动画,而不使用故事板,会发生什么?
private void AnimateX(FrameworkElement element, double xMoveStart, double xMoveEnd, double durationSeconds)
{
DoubleAnimation animation = new DoubleAnimation
{
From = xMoveStart,
To = xMoveEnd,
Duration = TimeSpan.FromSeconds(durationSeconds),
EasingFunction = new SineEase { EasingMode = EasingMode.EaseInOut }
};
element.BeginAnimation(Canvas.LeftProperty, animation);
}