How to animate points in polyline?

Emon Haque 3,176 Reputation points
2021-04-06T11:40:06.887+00:00

I've this in my window:

84788-test.png

I want that curve to rise up from horizontal line, x axis. So the initial position of each point will be (x,0) and will go up to (x,y). How to do that?

Here's the code for this plot:

class Plot : FrameworkElement  
{  
    VisualCollection children;  
    Canvas plotArea;  
    Polyline poly;  
    Line xAxis, yAxis;  
    public Plot() {  
        children = new VisualCollection(this);  
        initAxis();  
        initPlotArea();  
    }  
    void initAxis() {  
        xAxis = new Line() { Stroke = Brushes.LightBlue, StrokeThickness = 2 };  
        yAxis = new Line() { Stroke = Brushes.LightBlue, StrokeThickness = 2 };  
        children.Add(xAxis);  
        children.Add(yAxis);  
    }  
    void initPlotArea() {  
        plotArea = new Canvas() {  
            LayoutTransform = new ScaleTransform() { ScaleY = - 1 },  
            RenderTransform = new TransformGroup() {  
                Children = {  
                    new ScaleTransform(),  
                    new TranslateTransform()  
                }  
            }  
        };  
        children.Add(plotArea);  
        poly = new Polyline() { Stroke = Brushes.Black, StrokeThickness = 1 };  
        plotArea.Children.Add(poly);  
    }  
    void rearrangeAxis(Size size) {  
        xAxis.X2 = size.Width;  
        xAxis.Y1 = xAxis.Y2 = size.Height / 2;  
        yAxis.X1 = yAxis.X2 = size.Width / 2;  
        yAxis.Y2 = size.Height;  
        xAxis.Measure(size);  
        xAxis.Arrange(new Rect(xAxis.DesiredSize));  
        yAxis.Measure(size);  
        yAxis.Arrange(new Rect(yAxis.DesiredSize));  
    }  
    void rearrangePlotArea(Size size) {  
        plotArea.Width = size.Width;  
        plotArea.Height = size.Height;  
        var translate = (TranslateTransform)((TransformGroup)plotArea.RenderTransform).Children[1];  
        translate.X = size.Width / 2;  
        translate.Y = -size.Height / 2;  
        plotArea.Measure(size);  
        plotArea.Arrange(new Rect(plotArea.DesiredSize));  
        var points = new PointCollection();  
        var step = 0.5;  
        double xMin, xMax, yMax;  
        xMin = -5; xMax = 5; yMax = 25;  
        var seg = (xMax - xMin) / step;  
        double x = -5;  
        var xPos = -((TranslateTransform)((TransformGroup)plotArea.RenderTransform).Children[1]).X;  
        var xStep = plotArea.Width / seg;        
        for (int i = 0; i < seg+1; i++) {  
            var y = x * x;  
            var tY = (plotArea.Height / 2 / yMax) * y;  
            var point = new Point(xPos, tY);  
            points.Add(point);  
            xPos += xStep;  
            x += step;  
        }  
        poly.Points = points;  
    }  
    protected override Size ArrangeOverride(Size finalSize) {  
        rearrangeAxis(finalSize);  
        rearrangePlotArea(finalSize);  
        return finalSize;  
    }  
    protected override Visual GetVisualChild(int index) => children[index];  
    protected override int VisualChildrenCount => children.Count;  
}  

and in MainWindow.xaml I've used Plot like this:

<Grid Margin="20">  
    <cc:Plot />  
</Grid>  
Developer technologies | Windows Presentation Foundation
{count} votes

Answer accepted by question author
  1. Peter Fleischer (former MVP) 19,341 Reputation points
    2021-04-08T06:38:07.053+00:00

    Hi,
    you can use StoryBoard to animate PolyLine like in following demo (with your code):

    using System;  
    using System.Windows;  
    using System.Windows.Controls;  
    using System.Windows.Media;  
    using System.Windows.Media.Animation;  
    using System.Windows.Shapes;  
      
    namespace CC  
    {  
      
      class Plot : FrameworkElement  
      {  
        VisualCollection children;  
        Canvas plotArea;  
        Polyline poly;  
        Line xAxis, yAxis;  
        public Plot()  
        {  
          children = new VisualCollection(this);  
          initAxis();  
          initPlotArea();  
          this.Loaded += Plot_Loaded; // start Storyboard after loading  
        }  
      
        void initAxis()  
        {  
          xAxis = new Line() { Stroke = Brushes.LightBlue, StrokeThickness = 2 };  
          yAxis = new Line() { Stroke = Brushes.LightBlue, StrokeThickness = 2 };  
          children.Add(xAxis);  
          children.Add(yAxis);  
        }  
        void initPlotArea()  
        {  
          plotArea = new Canvas()  
          {  
            LayoutTransform = new ScaleTransform() { ScaleY = -1 },  
            RenderTransform = new TransformGroup()  
            {  
              Children = {  
                         new ScaleTransform(),  
                         new TranslateTransform()  
                     }  
            }  
          };  
          children.Add(plotArea);  
          poly = new Polyline() { Stroke = Brushes.Black, StrokeThickness = 1 };  
          plotArea.Children.Add(poly);  
        }  
        void rearrangeAxis(Size size)  
        {  
          xAxis.X2 = size.Width;  
          xAxis.Y1 = xAxis.Y2 = size.Height / 2;  
          yAxis.X1 = yAxis.X2 = size.Width / 2;  
          yAxis.Y2 = size.Height;  
          xAxis.Measure(size);  
          xAxis.Arrange(new Rect(xAxis.DesiredSize));  
          yAxis.Measure(size);  
          yAxis.Arrange(new Rect(yAxis.DesiredSize));  
        }  
        void rearrangePlotArea(Size size)  
        {  
          plotArea.Width = size.Width;  
          plotArea.Height = size.Height;  
          var translate = (TranslateTransform)((TransformGroup)plotArea.RenderTransform).Children[1];  
          translate.X = size.Width / 2;  
          translate.Y = -size.Height / 2;  
          plotArea.Measure(size);  
          plotArea.Arrange(new Rect(plotArea.DesiredSize));  
          var points = new PointCollection();  
          var step = 0.5;  
          double xMin, xMax, yMax;  
          xMin = -5; xMax = 5; yMax = 25;  
          var seg = (xMax - xMin) / step;  
          double x = -5;  
          var xPos = -((TranslateTransform)((TransformGroup)plotArea.RenderTransform).Children[1]).X;  
          var xStep = plotArea.Width / seg;  
          for (int i = 0; i < seg + 1; i++)  
          {  
            var y = x * x;  
            var tY = (plotArea.Height / 2 / yMax) * y;  
            var point = new Point(xPos, tY);  
            points.Add(point);  
            xPos += xStep;  
            x += step;  
          }  
          poly.Points = points;  
        }  
        protected override Size ArrangeOverride(Size finalSize)  
        {  
          rearrangeAxis(finalSize);  
          rearrangePlotArea(finalSize);  
          return finalSize;  
        }  
        protected override Visual GetVisualChild(int index) => children[index];  
        protected override int VisualChildrenCount => children.Count;  
      
        // animate Polyline  
      
        public DoubleAnimation da;  
        private Storyboard sb = new Storyboard();  
        ScaleTransform trans = new ScaleTransform() { ScaleY = 1 };  
        public void Plot_Loaded(object sender, RoutedEventArgs e)  
        {  
          if (da == null)  
          {  
            NameScope.SetNameScope(this, new NameScope());  
            this.RegisterName("scaleTransform", trans);  
            poly.LayoutTransform = trans;  
            da = new DoubleAnimation()  
            {  
              From = 0,  
              To = 1,  
              Duration = new Duration(TimeSpan.FromSeconds(1.0)),  
              RepeatBehavior = new RepeatBehavior(2),  
              AutoReverse = true  
            };  
            sb.Children.Clear();  
            sb.Children.Add(da);  
            Storyboard.SetTargetName(da, "scaleTransform");  
            Storyboard.SetTargetProperty(da, new PropertyPath(ScaleTransform.ScaleYProperty));  
            sb.Begin(this);  
          }  
        }  
      }  
    }  
    

    Result:

    85554-x.gif

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.