实现效果如下:
思路:基本原理同博文WPF实现聚光灯动画效果一致,难点在与正弦曲线的绘制和动态效果。
步骤:
1、自定义控件MyLoadingControl的封装
添加自定义Value属性:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(int), typeof(MyLoadingControl), new PropertyMetadata(null));
public int Value
{
get { return (int)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
xaml布局:
生成正弦曲线方法:
///
/// 得到正弦曲线
///
/// 水纹宽度
/// 水纹振幅
/// 水纹周期
/// 位移
/// 当前波浪高度
///
public StreamGeometry GetSinGeometry(double waveWidth, double waveA, double waveW, double offsetX, double currentK)
{
StreamGeometry g = new StreamGeometry();
using (StreamGeometryContext ctx = g.Open())
{
ctx.BeginFigure(new Point(0, 0), true, true);
for (int x = 0; x < waveWidth; x += 1)
{
double y = waveA * Math.Sin(x * waveW + offsetX) + currentK;
ctx.LineTo(new Point(x, y), true, true);
}
ctx.LineTo(new Point(waveWidth, 0), true, true);
}
return g;
}
添加DispatcherTimer计时器驱动:
private DispatcherTimer frameTimer;
private StreamGeometry myPathGeometry;
public MyLoadingControl()
{
InitializeComponent();
CompositionTarget.Rendering += UpdateRectangle;
frameTimer = new DispatcherTimer();
frameTimer.Tick += OnFrame;
frameTimer.Interval = TimeSpan.FromSeconds(3.0 / 60.0);
frameTimer.Start();
}
private void OnFrame(object sender, EventArgs e)
{
this.GeometryCanvas.Children.Clear();
if (Value > 100)
{
if(frameTimer != null)
frameTimer.Stop();
}
Value++;
myPathGeometry = GetSinGeometry(this.Width, -5, 1 / 30.0, -this.Width + this.Width * Value / 100, this.Height - this.Height * Value / 100);
GeometryGroup group = new GeometryGroup();
group.Children.Add(myPathGeometry);
Path myPath = new Path();
myPath.Fill = Brushes.Transparent;
myPath.Data = group;
this.GeometryCanvas.Children.Add(myPath);
}
private void UpdateRectangle(object sender, EventArgs e)
{
this.GeometryText.Clip = myPathGeometry;
}
2、主窗体调用