WPF开发之利用DrawingVisual绘制高性能曲线图
2023年7月19日发(作者:)
WPF开发之利⽤DrawingVisual绘制⾼性能曲线图前⾔项⽬中涉及到了⼼率检测,⽽且数据量达到了百万级别,通过WPF实现⼤数据曲线图时,尝试过最基础的Canvas来实现,但是性能堪忧,⽽且全部画出来也不实际。同时也尝试过找第三⽅的开源库,但是因为曲线图涉及到很多细节功能,第三⽅的肯定也没法满⾜。没办法,只能⾃⼰实现,上⽹查找后发现DrawingVisual这个玩意可以实现⾼性能画图,同时再搭配局部显⽰,这样就能实现⾃⼰想要的效果。话不多说,今天把⼤致的实现思路写⼀下,就不直接把项⽬的源码贴出来,写个简单的Demo就好了。正⽂1、⾸先新建个项⽬,然后创建个⾃定义控件,命名为CurveChartDrawingVisual,然后让它继承FrameworkElement。因为要使⽤DrawingVisual对象的话,需要为它创建⼀个主机容器。关于其他相关DrawingVisual的细节这⾥不做过多阐述,不明⽩的可以去微软官⽹看。2、实现的具体代码如下,相关细节有备注标注了。这⾥记得要重写⼀下VisualChildrenCount属性和重写GetVisualChild()⽅法,不然图画不出来public class CruveChartDrawingVisual : FrameworkElement{ private List visuals = new List(); private DrawingVisual Layer; private double offset_x = 0;//滑动条偏移值 private double y_scale;//y轴放⼼缩放⽐例 private List list_points;//曲线数据 private static int Top_Val_Max = 100;//y轴最⼤值 private static int Top_Val_Min = 0;//y轴最⼩值 private static int X_Sex = 20;//x轴分度值 private static int Y_Sex = 20;//x轴分度值 private static int Bottom = 30;//底部x轴坐标显⽰⾼度 Pen pen = new Pen(, 2); Pen primarygrid_pen = new Pen(, 1); Pen secondgrid_pen = new Pen(, 1); public CruveChartDrawingVisual() { ();//冻结笔,提⾼性能关键所在 primarygrid_(); secondgrid_(); Layer = new DrawingVisual(); (Layer); } public void SetupData(List points) { list_points = points; offset_x = 0; DrawContent(); } public void OffsetX(double offset) { offset_x = offset; DrawContent(); InvalidateVisual(); } private void DrawContent() { var dc = Open(); y_scale = ( - Bottom) / (Top_Val_Max - Top_Val_Min); var mat = new Matrix(); t(1, -1, 0, / 2); X = -offset_x; ansform(new MatrixTransform(mat)); //横线 for (int y = 0; y <= Top_Val_Max - Top_Val_Min; y += 10) { Point point1 = new Point(offset_x, y * y_scale + Bottom); Point point2 = new Point(offset_x + , y * y_scale + Bottom); if (y % Y_Sex == 0) { ne(primarygrid_pen, point1, point2); continue; } ne(secondgrid_pen, point1, point2); } //竖线与⽂字 for (int i = 0; i <= (offset_x + ); i += X_Sex * 2) { if (i < offset_x) { continue; } var point1 = new Point(i, Bottom); var point2 = new Point(i, (Top_Val_Max - Top_Val_Min) * y_scale + Bottom); //y轴⽂字 if (i % 100 == 0) { var text1 = new FormattedText(i + "", tCulture, Right, new Typeface("Verdana"), 16, ); var mat3 = new Matrix(); t(1, -1, i - / 2, 8 + / 2); ansform(new MatrixTransform(mat3)); xt(text1, new Point(i - / 2, 8)); (); } //表格刻度⽂字 if (i % 100 == 0) { for (int y = Top_Val_Min; y <= Top_Val_Max; y += 10) { if (y % Y_Sex == 0) { var text1 = new FormattedText(y + "", tCulture, Right, new Typeface("Verdana"), 12, ); var mat3 = new Matrix(); t(1, -1, i + 1, (y - Top_Val_Min) * y_scale + Bottom + / 2); ansform(new MatrixTransform(mat3)); xt(text1, new Point(i + 1, (y - Top_Val_Min) * y_scale + Bottom)); (); } } //深⾊竖线 ne(primarygrid_pen, point1, point2); continue; } //浅⾊竖线 ne(secondgrid_pen, point1, point2); } if (list_points != null) { for (int i = (int)offset_x; i < list_ - 1; i++) { if (i > offset_x + ) { break; } ne(pen, new Point(i, list_points[i] * y_scale + Bottom), new Point(i + 1, list_points[i + 1] * y_scale + Bottom)); } } (); (); } protected override int VisualChildrenCount => ; protected override Visual GetVisualChild(int index) { return visuals[index]; } protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) { DrawContent(); erSizeChanged(sizeInfo); } protected override void OnRender(DrawingContext drawingContext) { ctangle(, null, new Rect(0, 0, , )); er(drawingContext); }}3、接着测试⼀下,打开MainWindow,添加我们的⾃定义控件,这⾥局部显⽰需要搭配⼀个ScrollViewer来实现,记得这⾥没有将我们的⾃定义控件嵌⼊ScrollViewer,⽽是放⼀个Canvas来填充,代码如下 4、接着就是后台代码,⽐较简单,就是⾃动⽣成⼀个List,然后传给⾃定义控件,Canvas的宽度直接设置为List的长度,因为这⾥是⽔平⽅向⼀个像素点画⼀个点,然后滑动条滑动时再将对应的偏移值传递到控件,再通过偏移值更新视图public partial class MainWindow : Window{ private bool isAdd = true; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { List lists = new List(); int temp = 20; for (int i = 0; i < 60 * 60; i++) { if (isAdd) { (temp); temp ++; } else { (temp); temp --; } if (temp == 90) isAdd = false; if (temp == 10) isAdd = true; } = ; ata(lists); } private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { X(ntalOffset); }}5、运⾏效果如下,滑动条拖到哪⾥就显⽰哪⾥,这样就算数据量再⼤也没问题,这种曲线图跟常规的曲线图有点差别,这⾥更多的是提供⼀种思路以上就是WPF开发之利⽤DrawingVisual绘制⾼性能曲线图的详细内容,更多关于WPF DrawingVisual绘制曲线图的资料请关注其它相关⽂章!
发布者:admin,转转请注明出处:http://www.yc00.com/web/1689717795a280659.html
评论列表(0条)