失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > WPF 曲线图表控件(自制)(二)

WPF 曲线图表控件(自制)(二)

时间:2023-10-06 06:29:24

相关推荐

WPF 曲线图表控件(自制)(二)

原文:WPF 曲线图表控件(自制)(二)版权声明:本文为博主原创文章,未经博主允许。 /koloumi/article/details/77521872

如果还有不懂的请去资源区下载控件包含所有源码

/download/koloumi/9947692

接下来将代码上的。

界面调整部分的代码函数

还有一个重要的函数就是控件的MyChart_SizeChanged事件。

/// <summary>/// 尺寸改变/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void MyChart_SizeChanged(object sender, SizeChangedEventArgs e){Size newsize = e.NewSize;if(!e.WidthChanged){this.Width = newsize.Width;}if(!e.HeightChanged){this.Height = newsize.Height;}AdjustSize();AdjustScale();AdjustLines();AdjustLinesAndPoints();}

接下来是先看下定义的属性:

/// <summary>/// 数据集/// </summary>private Dictionary<string, DrawData> _data = new Dictionary<string, DrawData>();/// <summary>/// 坐标原点/// </summary>private Point _origPoint = new Point();/// <summary>/// X轴上的文字/// </summary>private List<TextBlock> _xTip = new List<TextBlock>();/// <summary>/// Y轴上的文字/// </summary>private List<TextBlock> _yTip = new List<TextBlock>();/// <summary>/// X轴的区间/// </summary>private VectorChart2 _xLimt = new VectorChart2(double.MaxValue, double.MinValue);/// <summary>/// Y轴的区间/// </summary>private VectorChart2 _yLimt = new VectorChart2(double.MaxValue, double.MinValue);/// <summary>/// 每个像素映射为多少距离/// </summary>private VectorChart2 _everyDisForPiexl = new VectorChart2();/// <summary>/// 缩放中心点的偏移/// </summary>private VectorChart2 _centerOffect = new VectorChart2(0, 0);/// <summary>/// 当前线的缩放比例/// </summary>private Vector4 _currentLinesScale = new Vector4(1, 1, 1, 1);/// <summary>/// 每个刻度之间的间隔/// </summary>private static double _everyDis = 30;

在这个控件上我们将每个刻度的间隔直接定死,这样有需要的时候直接修改刻度上的数值,而不用去移动刻度。如果尺寸变大只要增加刻度线,减少反之。在控件中用到的数据结构

/// <summary>/// 向量/// </summary>public struct VectorChart2{public double Vec1;public double Vec2;public VectorChart2(double v1, double v2){this.Vec1 = v1;this.Vec2 = v2;}/// <summary>/// Point 转换VectorChart2/// </summary>/// <param name="p"></param>public static implicit operator VectorChart2(Point p){return new VectorChart2(p.X, p.Y);}/// <summary>/// 乘法/// </summary>/// <param name="v1"></param>/// <param name="ratio"></param>/// <returns></returns>public static VectorChart2 operator * (VectorChart2 v1, double ratio){return new VectorChart2(v1.Vec1 * ratio, v1.Vec2 * ratio);}}/// <summary>/// 4维向量/// </summary>public struct Vector4{/// <summary>/// 空/// </summary>public static Vector4 Empty = new Vector4() { _isEmpty = true };public double Vec1;public double Vec2;public double Vec3;public double Vec4;/// <summary>/// 是否为空数据/// </summary>private bool _isEmpty;public Vector4(double Vec1, double Vec2, double Vec3, double Vec4){this.Vec1 = Vec1;this.Vec2 = Vec2;this.Vec3 = Vec3;this.Vec4 = Vec4;_isEmpty = false;}/// <summary>/// 重载等号运算符/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <returns></returns>public static bool operator ==(Vector4 v1, Vector4 v2){if (v1.Vec1 == v2.Vec1 && v1.Vec2 == v2.Vec2 && v1.Vec3 == v2.Vec3 && v1.Vec4 == v2.Vec4 && v1._isEmpty == v2._isEmpty){return true;}else{return false;}}/// <summary>/// 重载/// </summary>/// <param name="v1"></param>/// <param name="v2"></param>/// <returns></returns>public static bool operator !=(Vector4 v1, Vector4 v2){return !(v1 == v2);}public override bool Equals(object obj){return base.Equals(obj);}public override int GetHashCode(){return base.GetHashCode();}}/// <summary>/// 绘图数据/// </summary>public class DrawData : IDisposable{/// <summary>/// 线/// </summary>public Polyline Line;/// <summary>/// 线的标记点/// </summary>public List<Ellipse> Points = new List<Ellipse>();/// <summary>/// 源数据集合/// </summary>public ObservableCollection<Point> Ps = null;/// <summary>/// 极值/// </summary>public Vector4 Vec4 = Vector4.Empty;/// <summary>/// 提示/// </summary>public LineTitle LineTitle = new LineTitle();public DrawData(){}~DrawData(){this.Dispose();}#region IDisposable Supportprivate bool disposedValue = false; // 要检测冗余调用protected virtual void Dispose(bool disposing){if (!disposedValue){if (disposing){// TODO: 释放托管状态(托管对象)。Line = null;Ps = null;Points = null;LineTitle = null;}// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。// TODO: 将大型字段设置为 null。disposedValue = true;}}// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。// ~DrawData() {// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。// Dispose(false);// }// 添加此代码以正确实现可处置模式。public void Dispose(){// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。Dispose(true);// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。GC.SuppressFinalize(this);}#endregion}

调整曲线 刻度(直接修改)部分:

然后是调整所有绘图区的尺寸:

极值的调整 这里乘以0.15 是为了扩大上限 让初始曲线能够包括在视图中。

还有曲线刻度的添加式修改:(因为增加删除速度比较慢,所以只在有必要的时候调用这个,比如尺寸改变的时候,平时直接修改刻度即可)

/// <summary>/// 调整刻度\网格线(删除重新添加)/// </summary>protected void AdjustScale(){//if (!IsHaveLine) return;if (X_Axis.Width == 0 || X_Axis.Height == 0 || X_Axis.Width == double.NaN || X_Axis.Height == double.NaN) return;//if (GridLines.Width == 0 || GridLines.Height == 0 || GridLines.Width == double.NaN || double.IsNaN(GridLines.Height)) return;///清除X轴的刻度if (X_Axis.Children.Count > 1){X_Axis.Children.RemoveRange(1, X_Axis.Children.Count - 1);}///清除Y轴的刻度if (Y_Axis.Children.Count > 1){Y_Axis.Children.RemoveRange(1, Y_Axis.Children.Count - 1);}///清除网格线GridLines.Children.Clear();///清除刻度线的提示文字_xTip.Clear();_yTip.Clear();///添加X轴的for (double i = _origPoint.X; i < X_Axis.Width; i += _everyDis){Line x_scale = new Line();x_scale.StrokeThickness = 2;x_scale.Stroke = new SolidColorBrush(Colors.Black);x_scale.StrokeStartLineCap = PenLineCap.Round;x_scale.StrokeEndLineCap = PenLineCap.Round;x_scale.Width = 4;x_scale.Height = 20;x_scale.X1 = 2;x_scale.Y1 = 4;x_scale.X2 = 2;x_scale.Y2 = x_scale.Height;Canvas.SetLeft(x_scale, i);Canvas.SetTop(x_scale, 0);X_Axis.Children.Add(x_scale);///网格线GridLines.Children.Add(GetGridLine(new Point(i - 2, 0), false, GridLinesArea.Vec2));//double.IsNaN(GridLines.Height) ? GridLines.ActualHeight : GridLines.Height///添加提示文字TextBlock block = new TextBlock();block.FontSize = 10;block.Text = i.ToString();Canvas.SetLeft(block, i);Canvas.SetTop(block, 25);_xTip.Add(block);X_Axis.Children.Add(block);}///添加Y轴的for (double i = _origPoint.Y; i < Y_Axis.Height; i += _everyDis){Line y_scale = new Line();y_scale.StrokeThickness = 2;y_scale.Stroke = new SolidColorBrush(Colors.Black);y_scale.StrokeStartLineCap = PenLineCap.Round;y_scale.StrokeEndLineCap = PenLineCap.Round;y_scale.Width = 20;y_scale.Height = 4;y_scale.X1 = 4;y_scale.Y1 = 2;y_scale.X2 = y_scale.Width;y_scale.Y2 = 2;Canvas.SetBottom(y_scale, i + 1);Canvas.SetRight(y_scale, 2);Y_Axis.Children.Add(y_scale);///网格线GridLines.Children.Add(GetGridLine(new Point(i - 2, 0), true, GridLinesArea.Vec1));//double.IsNaN(GridLines.Width) ? GridLines.ActualWidth : GridLines.Width)///添加提示文字TextBlock block = new TextBlock();block.FontSize = 10;block.Text = i.ToString();Canvas.SetBottom(block, i);Canvas.SetRight(block, 10);_yTip.Add(block);Y_Axis.Children.Add(block);}}

调整线和点:(主要是,缩放和拖动)

调整线和点的大小比例AdjustLinesAndPointsSize 这个函数可以删掉,后来发现没有用。鼠标滚轮事件:

/// <summary>/// 鼠标滚轮事件/// </summary>/// <param name="e"></param>protected override void OnMouseWheel(MouseWheelEventArgs e){base.OnMouseWheel(e);VectorChart2 curPDraw = (VectorChart2)e.GetPosition(Draw);VectorChart2 curPLinesAndPoint = (VectorChart2)e.GetPosition(DrawLineAndPoint);double delta = 1;if(e.Delta >= 120){delta = 1.2;}else if(e.Delta <= -120){delta = (double)5 / (double)6;}if (IsXZoom){DrawLineAndPoint.Width *= delta;curPDraw.Vec1 *= delta;curPLinesAndPoint.Vec1 *= delta;}if (IsYZoom){DrawLineAndPoint.Height *= delta;curPDraw.Vec2 *= delta;curPLinesAndPoint.Vec2 *= delta;}_currentLinesScale.Vec4 *= delta;//Canvas.SetLeft(DrawLineAndPoint, curPDraw.Vec1 - curPLinesAndPoint.Vec1);//Canvas.SetBottom(DrawLineAndPoint, -(DrawArea.Vec2 - (curPLinesAndPoint.Vec2 - curPDraw.Vec2)));///调整刻度AdjustLines();AdjustLinesAndPoints();}

重置按钮:

鼠标移动的时候计算移动的差值然后调用该函数:

获取偏移量函数:

/// <summary>/// 获取偏移量/// </summary>/// <returns></returns>protected VectorChart2 GetOffectValue(VectorChart2 offectValue){return new VectorChart2( -offectValue.Vec1 * _everyDisForPiexl.Vec1, offectValue.Vec2 * _everyDisForPiexl.Vec2);}

至此全部结束 如果还有不懂的请去资源区下载控件包含所有源码

/download/koloumi/9947692

如果觉得《WPF 曲线图表控件(自制)(二)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。