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: