做阿里巴巴英文网站,网站备案需要多长时间,云南网络推广报价明细,公司网站备案去哪里备案一、前言项目中涉及到了心率监测#xff0c;而且数据量达到了百万级别#xff0c;通过WPF实现大数据曲线图时#xff0c;尝试过最基础的Canvas来实现#xff0c;但是性能堪忧#xff0c;而且全部画出来也不实际。同时也尝试过找第三方的开源库#xff0c;但是因为曲线图涉… 一、前言项目中涉及到了心率监测而且数据量达到了百万级别通过WPF实现大数据曲线图时尝试过最基础的Canvas来实现但是性能堪忧而且全部画出来也不实际。同时也尝试过找第三方的开源库但是因为曲线图涉及到很多细节功能第三方的肯定也没法满足。没办法只能自己实现上网查找后发现DrawingVisual这个玩意可以实现高性能画图同时再搭配局部显示这样就能实现自己想要的效果。话不多说今天把大致的实现思路写一下就不直接把项目的源码贴出来写个简单的Demo就好了。二、正文1、首先新建个项目然后创建个自定义控件命名CurveChartDrawingVisual然后让它继承FrameworkElement。因为要使用DrawingVisual对象的话需要为它创建一个主机容器。关于其他相关DrawingVisual的细节这里不做过多阐述不明白的可以去微软官网看。2、实现的具体代码如下相关细节有备注标注了。这里记得要重写一下VisualChildrenCount属性和重写 GetVisualChild() 方法不然图画不出来public class CruveChartDrawingVisual : FrameworkElement
{private ListVisual visuals new ListVisual();private DrawingVisual Layer;private double offset_x 0;//滑动条偏移值private double y_scale;//y轴方向缩放比例private Listint 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;//y轴分度值private static int Bottom 30;//底部x轴坐标显示高度Pen pen new Pen(Brushes.Green, 2);Pen primarygrid_pen new Pen(Brushes.Black, 1);Pen secondgrid_pen new Pen(Brushes.Gray, 1);public CruveChartDrawingVisual(){pen.Freeze();//冻结笔提高性能关键所在primarygrid_pen.Freeze();secondgrid_pen.Freeze();Layer new DrawingVisual();visuals.Add(Layer);}public void SetupData(Listint points){list_points points;offset_x 0;DrawContent();}public void OffsetX(double offset){offset_x offset;DrawContent();InvalidateVisual();}private void DrawContent(){var dc Layer.RenderOpen();y_scale (RenderSize.Height - Bottom) / (Top_Val_Max - Top_Val_Min);var mat new Matrix();mat.ScaleAt(1, -1, 0, RenderSize.Height / 2);mat.OffsetX -offset_x;dc.PushTransform(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 RenderSize.Width, y * y_scale Bottom);if (y % Y_Sex 0){dc.DrawLine(primarygrid_pen, point1, point2);continue;}dc.DrawLine(secondgrid_pen, point1, point2);}//竖线与文字for (int i 0; i (offset_x RenderSize.Width); 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 , CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(Verdana), 16, Brushes.Black);var mat3 new Matrix();mat3.ScaleAt(1, -1, i - text1.Width / 2, 8 text1.Height / 2);dc.PushTransform(new MatrixTransform(mat3));dc.DrawText(text1, new Point(i - text1.Width / 2, 8));dc.Pop();}//表格刻度文字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 , CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(Verdana), 12, Brushes.Black);var mat3 new Matrix();mat3.ScaleAt(1, -1, i 1, (y - Top_Val_Min) * y_scale Bottom text1.Height / 2);dc.PushTransform(new MatrixTransform(mat3));dc.DrawText(text1, new Point(i 1, (y - Top_Val_Min) * y_scale Bottom));dc.Pop();}}//深色竖线dc.DrawLine(primarygrid_pen, point1, point2);continue;}//浅色竖线dc.DrawLine(secondgrid_pen, point1, point2);}if (list_points ! null){for (int i (int)offset_x; i list_points.Count - 1; i){if (i offset_x RenderSize.Width){break;}dc.DrawLine(pen, new Point(i, list_points[i] * y_scale Bottom), new Point(i 1, list_points[i 1] * y_scale Bottom));}}dc.Pop();dc.Close();}protected override int VisualChildrenCount visuals.Count;protected override Visual GetVisualChild(int index){return visuals[index];}protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo){DrawContent();base.OnRenderSizeChanged(sizeInfo);}protected override void OnRender(DrawingContext drawingContext){drawingContext.DrawRectangle(Brushes.White, null, new Rect(0, 0, RenderSize.Width, RenderSize.Height));base.OnRender(drawingContext);}
}3、接着测试一下打开MainWindow添加我们的自定义控件这里局部显示需要搭配一个ScrollViewer来实现记得这里没有将我们的自定义控件嵌入ScrollViewer而是放一个Canvas来填充代码如下Gridlocal:CruveChartDrawingVisual x:Namecurve Margin0,15,0,20 /ScrollViewerNamescrollHorizontalScrollBarVisibilityAutoScrollChangedScrollViewer_ScrollChangedVerticalScrollBarVisibilityDisabledCanvas x:Namecanvas Height1 //ScrollViewer
/Grid4、接着就是后台代码比较简单就是自动生成一个List然后传给自定义控件Canvas的宽度直接设置为List的长度因为这里是水平方向一个像素点画一个点然后滑动条滑动时再将对应的偏移值传递到控件再通过偏移值更新视图public partial class MainWindow : Window
{private bool isAdd true;public MainWindow(){InitializeComponent();}private void Window_Loaded(object sender, RoutedEventArgs e){Listint lists new Listint();int temp 20;for (int i 0; i 60 * 60; i){if (isAdd){lists.Add(temp);temp ;}else{lists.Add(temp);temp --;}if (temp 90) isAdd false;if (temp 10) isAdd true;}canvas.Width lists.Count;curve.SetupData(lists);}private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e){curve.OffsetX(scroll.HorizontalOffset);}
}5、运行效果如下滑动条拖到哪里就显示哪里这样就算数据量再大也没问题这种曲线图跟常规的曲线图有点差别这里更多的是提供一种思路。[1]参考资料[1]链接: https://www.cnblogs.com/cong2312/p/15921146.html