Получить плавную анимацию, используя #wpf? - PullRequest
0 голосов
/ 01 мая 2020

Я занимаюсь разработкой простого средства просмотра графиков. Я получил его с помощью простых эллипсов и линий на холсте.

Теперь я хочу, чтобы на графике было несколько точек. Вы можете представить это как машины, проезжающие по улицам города.

Чтобы иметь что-то, что могло бы запускать логи анимации c с определенной скоростью, я установил DispatcherTimer и сделал там все логи анимации c. Это работает, но это действительно изменчиво. Если честно, я не удивлен. Я понимаю, что этот способ рендеринга на холст и анимацию с использованием системы событий не такой, как вы могли бы ожидать, чтобы он работал так же гладко, как, например, движок 2D-игр.

Итак, мой вопрос в том, чтобы быть новичком ie для WPF, что я могу сделать, чтобы улучшить производительность / точность? Я видел, что существует пакет Skia, доступный для c# (SkiaSharp), который, я думаю, может улучшить производительность рендеринга, но как насчет запуска logi c с «точной» (без реального времени здесь) частотой кадров?

Ответы [ 3 ]

1 голос
/ 01 мая 2020

Производительность не была одной из главных целей разработки WPF. Если вам нужны высокоскоростные пользовательские анимации, которые не могут быть реализованы с помощью системы анимации WPF, то вам лучше извлечь непосредственно из 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);
    }
}
1 голос
/ 01 мая 2020

Необходимо использовать Animat ios для отображения данных требуемым образом. WPF-анимации предназначены для плавного рендеринга и демонстрируют лучшую производительность при работе диспетчера.

В простейшем случае вам потребуется запустить двойную анимацию, чтобы обновить отдельное свойство модели представления. Затем пересчитайте свойства (размер, положение и т. Д. c) различных объектов на основе этого значения.

Другим возможным решением является определение собственного класса анимации. Это решение продемонстрировано в WPF Tutorial - Part 2: Написание собственного класса анимации . Это решение обеспечивает большую гибкость, но, как правило, вы получите аналогичное значение (вы можете считать его «прошедшим время»), которое можно использовать для расчета параметров объектов.

0 голосов
/ 03 мая 2020

Для вашего случая в WPF есть специальный механизм - анимация. Я бы порекомендовал вам прочитать эту статью: Как: анимировать объект вдоль пути .

Ниже приведен пример обхода простого графика. Также обратите внимание, что в примере я использую один предопределенный путь (для простоты). На практике вы можете динамически создавать такие пути и анимации из кода.

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...