繁体   English   中英

使用#wpf 获得流畅的动画?

[英]Get smooth animations using #wpf?

我正在开发一个简单的图形查看器。 我在 canvas 上使用简单的椭圆和线条很好地渲染了它。

现在,我想让一些点在图表中导航。 你可以把它想象成穿过城市街道的汽车。

为了拥有可以以一定速率运行 animation 逻辑的东西,我设置了一个 DispatcherTimer 并在那里执行了所有 animation 逻辑。 它有效,但它真的很不稳定。 说实话,我并不感到惊讶。 我知道,这种在 canvas 上渲染并使用事件系统制作动画的方式并不像 2D 游戏引擎那样运行流畅。

所以,我的问题是,作为 WPF 的新手,我能做些什么来提高性能/准确性吗? 我已经看到存在一个可用于 c# (SkiaSharp) 的 Skia package,我认为它可以提高渲染性能,但是以“准确”(这里没有实时操作系统)帧速率运行逻辑呢?

性能不是 WPF 的主要设计目标之一。 如果您需要无法使用 WPF animation 系统实现的高速自定义动画,那么您最好直接从 FrameworkElement 派生并覆盖 OnRender:

public class CustomControl : FrameworkElement
{
    public CustomControl()
    {
        // leave this line in to force a render of the control for each frame
        CompositionTarget.Rendering += (s, e) => InvalidateVisual();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        var angle = Math.PI * DateTime.Now.Ticks / 10000000;
        var xoffset = 100 + (int)(50 * Math.Sin(angle));
        var yoffset = 100 + (int)(50 * Math.Cos(angle));
        drawingContext.DrawEllipse(Brushes.Red, null, new Point(xoffset, yoffset), 50, 50);
    }
}

需要使用 Animatios 以所需的方式显示数据。 WPF 动画旨在用于平滑渲染并在调度程序时展示更好的性能。

在最简单的情况下,您需要启动 Double animation 来更新视图 model 的单个属性。 然后根据该值重新计算不同对象的属性(大小、位置等)。

另一种可能的解决方案是定义自定义 animation class。 此解决方案在WPF 教程 - 第 2 部分:编写自定义 animation class中进行了演示。 此解决方案提供了更大的灵活性,但通常您将获得可用于计算对象设置的类似值(您可以将其视为“经过时间”)。

WPF 中有一个特殊机制仅适用于您的情况 - 动画。 我建议您阅读这篇文章: 如何:沿路径为 Object 设置动画

下面是一个遍历简单图的例子。 另请注意,在示例中,我使用了一个预定义的路径(为简单起见)。 在实践中,您可以从代码隐藏动态创建此类路径和动画。

<Canvas>
    <Canvas.Resources>
        <PathGeometry x:Key="AnimationPath" Figures="M 100,100 L 200,150 L 230,250 L 150,300 L 100,100"/>
    </Canvas.Resources>

    <Line X1="115" X2="215" Y1="115" Y2="165" Stroke="Green" StrokeThickness="5"/>
    <Line X1="215" X2="245" Y1="165" Y2="265" Stroke="Green" StrokeThickness="5"/>
    <Line X1="245" X2="165" Y1="265" Y2="315" Stroke="Green" StrokeThickness="5"/>
    <Line X1="165" X2="115" Y1="315" Y2="115" Stroke="Green" StrokeThickness="5"/>

    <Ellipse Width="30" Height="30" Canvas.Left="100" Canvas.Top="100" Fill="Red"/>
    <Ellipse Width="30" Height="30" Canvas.Left="200" Canvas.Top="150" Fill="Red"/>
    <Ellipse Width="30" Height="30" Canvas.Left="230" Canvas.Top="250" Fill="Red"/>
    <Ellipse Width="30" Height="30" Canvas.Left="150" Canvas.Top="300" Fill="Red"/>

    <Ellipse x:Name="traveller" Width="30" Height="30" Fill="Blue">
        <Ellipse.RenderTransform>
            <TranslateTransform x:Name="transform"/>
        </Ellipse.RenderTransform>
    </Ellipse>

    <Canvas.Triggers>
        <EventTrigger RoutedEvent="Loaded">
            <BeginStoryboard>
                <Storyboard RepeatBehavior="Forever">
                    <DoubleAnimationUsingPath PathGeometry="{StaticResource AnimationPath}"
                                              Storyboard.TargetName="transform"
                                              Storyboard.TargetProperty="X"
                                              Source="X"
                                              Duration="0:0:10"/>

                    <DoubleAnimationUsingPath PathGeometry="{StaticResource AnimationPath}"
                                              Storyboard.TargetName="transform"
                                              Storyboard.TargetProperty="Y"
                                              Source="Y"
                                              Duration="0:0:10"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Canvas.Triggers>
</Canvas>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM