Avalonia: cómo animar puntos en la ruta usando código

Estoy tratando de averiguar cómo hacer animaciones en Avalonia.

Tengo un camino con 4 segmentos de línea y quiero animar cada punto a una nueva posición. En WPF lo he hecho así:

        public void AnimatePoints(PointCollection pts, TimeSpan timespan, bool randomized = true, Action onFinished = null)
        {
            Points = PointCollection.Parse(PathString);

            //PathFigure needs an animation too (for the start point), otherwise the first point always stays in one place
            var pfa = new PointAnimation(pts[0], timespan);

            if (onFinished != null)
            {
                pfa.Completed += (sender, args) => onFinished();
            }

            PathFigure.BeginAnimation(PathFigure.StartPointProperty, pfa);

            for (int i = 0; i < pts.Count; i++)
            {
                var pa = new PointAnimation(pts[i], timespan);
                if (randomized)
                {
                    LineSegments[i].BeginAnimation(LineSegment.PointProperty, pa);
                }
                else
                {
                    LineSegments[i].BeginAnimation(LineSegment.PointProperty, pa);
                }
            }
        }

¿Cómo puedo hacer lo mismo en Avalonia usando código? Lo intenté con PathTransition pero ni PathFigure ni LineSegments son animables.

Answer

No creo que haya un animador incorporado, pero en Avalonia puedes hacer animadores personalizados como ese:

public class MorphAnimator : Animator<Geometry>
{
    public override Geometry Interpolate(double progress, Geometry oldValue, Geometry newValue)
    {
        var clone = (oldValue as PathGeometry).ClonePathGeometry();

        Morph.To(clone, newValue as PathGeometry, progress);

        return clone;
    }
}

y registrarse

Animation.RegisterAnimator<MorphAnimator>(prop => typeof(Geometry).IsAssignableFrom(prop.PropertyType));

Código de ejemplo: https://github.com/wieslawsoltes/MorphingDemo

También puedes hacer animadores personalizados desde Xaml:

<UserControl 
  xmlns="https://github.com/avaloniaui" 
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
  xmlns:pages="clr-namespace:RenderDemo.Pages"
  x:Class="RenderDemo.Pages.CustomAnimatorPage"
  MaxWidth="600">
  <Grid>
    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">
      <TextBlock.Styles>
        <Style Selector="TextBlock">
          <Style.Animations>
            <Animation Duration="0:0:1" IterationCount="Infinite">
              <KeyFrame Cue="0%">
                <Setter Property="Text" Value="" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
              </KeyFrame>
              <KeyFrame Cue="100%">
                <Setter Property="Text" Value="0123456789" Animation.Animator="{x:Type pages:CustomStringAnimator}"/>
              </KeyFrame>
            </Animation>
          </Style.Animations>
        </Style>
      </TextBlock.Styles>
    </TextBlock>
  </Grid>
</UserControl>

Animador:

using Avalonia.Animation.Animators;

namespace RenderDemo.Pages
{
    public class CustomStringAnimator : Animator<string>
    {
        public override string Interpolate(double progress, string oldValue, string newValue)
        {
            if (newValue.Length == 0) return "";
            var step = 1.0 / newValue.Length;
            var length = (int)(progress / step);
            var result = newValue.Substring(0, length + 1);
            return result;
        }
    }
}