最近一致在开发能源平台,平台中很多能耗数据都是通过使用微软的chart控件进行图形呈现的。考虑到要给用户更为直观的呈现效果,需要对原有控件的功能进行扩展。微软chart控件没有第三方样chart样式炫酷,但是胜在可定制性强,中文手册详细,很多效果能够自己写出来。
主要实现功能:1.最大值,最小值,平均值展示 2.鼠标移动到数据点绘制竖线,用tooltip的方式展示数据
最终呈现效果如图:
解决方案:
(1)最大值,最小值,平均值呈现
之前在网上找了好久都没有想要的效果,第三方控件往往都能直接设置。最开始我的解决方法是在ChartArea中添加单独的series展示最值,但是呈现效果不佳:
在看了微软的技术手册后,发现可以在ChartArea中添加Stripline实现。以插入最大值线条为例,代码如下:
//最大线条 double max = ammeter.Max(); StripLine stripMax = new StripLine(); stripMax.Text = string.Format("最大:{0:F}", max);//展示文本 stripMax.BackColor = Color.FromArgb(208, 109, 106);//背景色 stripMax.Interval = 0;//间隔 stripMax.IntervalOffset = max;//偏移量 stripMax.StripWidth = 0.001;//线宽 stripMax.ForeColor = Color.White;//前景色 stripMax.TextAlignment = StringAlignment.Near;//文本对齐方式 chartInfo.ChartAreas["ammeter"].AxisY.StripLines.Add(stripMax);//添加到ChartAreas中
(2)实现鼠标移动到数据点绘制竖线,用tooltip的方式展示数据
chart中可以对画图区域使用HitTest进行数据点检测,之前的方案是在鼠标移动的过程中对当前鼠标的坐标区域(x为当前坐标,y为画图区域的高 )进行数据检测,移动的过程中绘制跟随鼠标的线条。实现后发现效果并不是很好,HitTest在数据点周围的series都会判定为数据点,所以线条一直在绘制,而想要的效果鼠标移动的过程中仅在数据点时才绘制竖线。
要在数据点位置绘制线条需要获得数据点的相对坐标,网上一直没有找到解决办法。起初通过x,y轴的偏移量,0点的坐标,绘图区域的坐标可以实现相对坐标的获取,但是发现这样有时计算会有很大的偏差。同样通过查找技术手册后,发现微软给了获取x,y轴相对坐标的方法。
Point lastPoint = new Point();//上次点的坐标 ToolTip tp = new ToolTip();//tooltip展示条 //绘制竖线坐标 Point p1 = new Point(0, 0); Point p2 = new Point(0, 0); /// <summary> /// 鼠标移动事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void chartInfo_MouseMove(object sender, MouseEventArgs e) { this.Refresh();//刷新chart,使用clear会使chart上的图形完全清空 Pen pen = new Pen(Color.Yellow); Graphics g = chartInfo.CreateGraphics(); string seriesInfo = ""; //tooltip文本 if (e.Location != lastPoint)//如果在上次点的位置不进行操作,此处操作会引发chart控件的refresh操作造成界面闪烁 { for (int y = 0; y <= chartInfo.Size.Height; y++)//线条范围进行碰撞检测 { HitTestResult result = chartInfo.HitTest(e.X, y); if (result.ChartElementType == ChartElementType.DataPoint) { foreach (DataPoint dpp in result.Series.Points)//数据点默认样式 使用索引的方式修改偶尔会出现无法正常修改完 { dpp.MarkerStyle = MarkerStyle.Diamond; dpp.MarkerColor = Color.White; dpp.MarkerSize = 5; } int i = result.PointIndex; DataPoint dp = result.Series.Points[i]; dp.MarkerStyle = MarkerStyle.Star4;//捕获到数据点的样式 dp.MarkerColor = Color.Orange; dp.MarkerSize = 15; //获取数据点的相对坐标 p1 = new Point((int)chartInfo.ChartAreas["ammeter"].AxisX.ValueToPixelPosition(dp.XValue), 0); p2 = new Point((int)chartInfo.ChartAreas["ammeter"].AxisX.ValueToPixelPosition(dp.XValue), chartInfo.Size.Height); seriesInfo = string.Format("分项:{0} 时间:{1} 能耗值:{2}", result.Series.LegendText, DateTime.FromOADate(dp.XValue), dp.YValues[0]); break; } } tp.AutoPopDelay = 5000;//展示tooltip tp.ShowAlways = false; tp.IsBalloon = true; tp.SetToolTip(chartInfo, seriesInfo); } lastPoint = e.Location;//记录本次位置 g.DrawLine(pen, p1, p2);//绘制竖线 }
写在最后
微软技术手册真香
原文地址:https://www.cnblogs.com/akagreen/p/10335091.html