Win2d UWP жидкая анимационная линия холста - PullRequest
0 голосов
/ 07 января 2020

Я должен получить плавную анимацию линии, нарисованной с помощью Win2d. Ниже приведен код, который имитирует мою проблему.

MainPage.xaml:

     <canvas:CanvasAnimatedControl x:Name="animatedControl" 
                                   Margin="0,30,0,0"
                                   Height="500"
                                   Draw="OnDraw"/>

MainPage.xaml.cs:

    private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
    {
        CanvasDrawingSession ds = args.DrawingSession;

        double height = sender.Size.Height;
        double width = sender.Size.Width;

        Random random = new Random();

        double pointHeigth = random.Next(0, 300);

        var point1 = new Vector2((float)(width / 2), (float)height);
        var point2 = new Vector2((float)(width / 2), (float)height - (float)pointHeigth);

        CanvasSolidColorBrush brush = new CanvasSolidColorBrush(sender, Colors.Green);

        ds.DrawLine(point1, point2, brush, (float)10);
    }

Таким образом, я получаю волан анимация как получить плавную анимацию линии?

Я заявляю, что должен использовать холст с win2d.

Заранее спасибо.

ОБНОВЛЕНИЕ (Мой код это не работает)

    private Vector2 _point1;
    private Vector2 _point2;
    private Vector2 _targetPoint;
    private TimeSpan _animationElapsedTime = TimeSpan.FromMilliseconds(100);

    public MainPage()
    {
        this.InitializeComponent();
    }

    private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
    {
        CanvasDrawingSession ds = args.DrawingSession;

        double height = sender.Size.Height;
        double width = sender.Size.Width;


        Random random = new Random();

        double pointHeigth = random.Next(0, 300);

        var _point1 = new Vector2((float)(width / 2), (float)height);

        var _point2 = new Vector2((float)(width / 2), (float)height - (float)pointHeigth);

        CanvasSolidColorBrush brush = new CanvasSolidColorBrush(sender, Colors.Green);

        ds.DrawLine(_point1, _point2, brush, (float)10);
    }

    private Vector2 Tween(Vector2 sourcePoint, Vector2 targetPoint, float percentage)
    {
        return new Vector2(targetPoint.X + (targetPoint.X - sourcePoint.X) * percentage, targetPoint.Y + (targetPoint.Y - sourcePoint.Y) * percentage);
    }

    private void OnUpdate(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedUpdateEventArgs args)
    {
        _animationElapsedTime += args.Timing.ElapsedTime;
        var percentage = Math.Min(_animationElapsedTime.TotalSeconds / 5.0f, 1f);
        _point2 = Tween(_point1, _targetPoint, (float)percentage);
    }

ОБНОВЛЕНИЕ 2 MyCode:

    double previuosData = 0;
    bool isDraw = false;

    public MainPage()
    {
        this.InitializeComponent();
    }

    private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
    {
        if (isDraw)
            return;

        CanvasDrawingSession ds = args.DrawingSession;

        double height = sender.Size.Height;
        double width = sender.Size.Width;

        CanvasSolidColorBrush brush = new CanvasSolidColorBrush(sender, Colors.Green);

        Random random = new Random();

        double pointHeigth = random.Next(0, 500);

        var point1 = new Vector2((float)(width / 2), (float)height);

        if (pointHeigth > previuosData)
        {
            for (double a = previuosData; a <= pointHeigth; a++)
            {
                isDraw = true;
                var point2 = new Vector2((float)(width / 2), (float)height - (float)a);
                ds.DrawLine(point1, point2, brush, (float)10);
            }
            isDraw = false;
        }
        else
        {
            for (double a = previuosData; a >= pointHeigth; a--)
            {
                isDraw = true;
                var point2 = new Vector2((float)(width / 2), (float)height - (float)a);
                ds.DrawLine(point1, point2, brush, (float)10);
            }
            isDraw = false;
        }

        previuosData = pointHeigth;
    }

таким образом я делаю анимацию немного более плавной, но с помощью для l oop этого недостаточно как я могу улучшить?

1 Ответ

0 голосов
/ 07 января 2020

Кажется, вы используете Random, и это генерирует случайное число из заданного диапазона в каждом отдельном кадре. Таким образом, это означает, что 60 раз в секунду вторая точка будет случайным образом перемещаться вверх и вниз.

Сравните с чем-то вроде следующего:

private bool _adding = true;
private int _currentHeightOffset = 0;
private void OnDraw(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedDrawEventArgs args)
{
    CanvasDrawingSession ds = args.DrawingSession;

    double height = sender.Size.Height;
    double width = sender.Size.Width;

    var point1 = new Vector2((float)(width / 2), (float)height);
    var point2 = new Vector2((float)(width / 2), (float)height - (float)_currentHeight);

    CanvasSolidColorBrush brush = new CanvasSolidColorBrush(sender, Colors.Green);

    ds.DrawLine(point1, point2, brush, (float)10);
    if (_adding)
    {
       _currentHeightOffset++;
    }
    else
    {
       _currentHeightOffset--;
    }
    if (_currentHeightOffset == 0 || _currentHeightOffset == 300 )
    {
       _adding = !_adding;
    }        
}

Теперь в этом примере я перемещаю пиксель точки на пиксель в каждом кадре, пока он не достигнет 300, а затем go вернется к 0. Таким образом, результатом должна стать линия, которая выглядит фиксированной в point1 и перемещается и растягивается вверх и вниз.

Ключ в том, что значения больше не случайные, а предсказуемые от кадра к кадру.

Обновление

Как я уже говорил в комментариях, вы можете создать эффект "анимации движения" между двумя точками.

Мы бы использовали следующий метод:

private Vector2 Tween(Vector2 sourcePoint, Vector2 targetPoint, float percentage)
{
   return new Vector2( 
       targetPoint.X + (targetPoint.X - sourcePoint.X)*percentage,
       targetPoint.Y + (targetPoint.Y - sourcePoint.Y)*percentage)  
}

Теперь, если вы хотите анимировать между этими двумя точками в течение 5 секунд, вы можете сделать что-то вроде:

private Vector2 _point2;
private TimeSpan _animationElapsedTime = TimeSpan.Zero;

private void OnUpdate(Microsoft.Graphics.Canvas.UI.Xaml.ICanvasAnimatedControl sender, 
      Microsoft.Graphics.Canvas.UI.Xaml.CanvasAnimatedUpdateEventArgs args)
{
    _animationElapsedTime += args.Timing.ElapsedTime;
    var percentage = Math.Min(_animationElapsedTime.TotalSeconds / 5.0f, 1f);
    _point2 = Tween(_point1, _targetPoint, percentage);
}

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

...