C#中的chart控件是非常强大的,可以轻松实现数据的可视化,用于自己的数据处理是非常方便的。
在我之前的一篇文章中,我讲了如何对chart中的数据进行框选、删除、平移等功能(详细见C#实现chart控件数据点的框选、删除、平移),这次我又新添加了一个功能,chart的漫游。我就是在自己处理数据过程中慢慢摸索,慢慢增加我的程序的功能,下面就来看看如何实现chart图表的漫游。
在chart中,有时需要放大查看数据,但是很容易出现下面的情况,数据超出显示范围了。
虽然有滚动条按钮,但每次都要点滚动条,感觉也挺累的,而且不是很好控制滚动大小,所以我想到了要实现一个chart图表的漫游功能。
要实现漫游功能,需要了解chart坐标轴的一个属性,它就是数据视图位置属性。
这个Position表示的是滚动条左端当前的视图位置,那么就容易想到,漫游功能的实现其实就是设置这个Position的值。根据我们的习惯,以X轴方向为例,当按住鼠标从右往左拖动时,chart的视图应该是从左向右移动,也就是往X轴变大的方向显示数据。那么我们只要记住按下鼠标时刻的坐标start.X和松开鼠标时刻的坐标end.X,两者做差,再加上当前的Position,就是漫游后新的Position的位置。代码表示就是
chart1.ChartAreas[0].AxisX.ScaleView.Position += start.X - end.X;
这里要注意,虽然根据实现方法是这样列出式子,但是等式两边的坐标系不同,左边的Position的坐标系是chart数据坐标系,而右边是chart控件坐标系,关于这两个坐标系的转换,可以通过上面的链接去看我上一篇文章的介绍,这里不再赘述。所以这里我们需要把chart控件坐标系转换到chart数据坐标系。根据反算公式,可以知道
chart1.Series[0].Point.XValue = chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum +
(x * 100.0 / (double)chart1.Width - (double)chart1.ChartAreas[0].InnerPlotPosition.X) / xpercent;
那么只要把XValue替换成Position,x替换成start.X-end.X,就是我们要求的新的Position,代码表示就是
chart1.ChartAreas[0].AxisX.ScaleView.Position = chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum +
((double)(start.X - end.X) * 100.0 / (double)chart1.Width - (double)chart1.ChartAreas[0].InnerPlotPosition.X) / xpercent;
这就是X轴方向的漫游公式。
Y轴方向的漫游,类似X轴,但是很重要一点要注意,chart控件坐标系的Y轴和chart数据点坐标系的Y轴方向是相反的,前者向下为正,后者向上为正,所以在转换前,还需要把向下的坐标系转换到向上的方向上来,这个转换很简单,设同一个点,在chart控件坐标系中Y坐标是y2,在chart数据点坐标系中Y坐标是y1,那么就有
y1 = chart1.Height - y2
而且还有一点需要注意,鼠标从上往下拖动时,Y值其实是增大的,那么这里就和X轴相反了,是
chart1.ChartAreas[0].AxisY.ScaleView.Position += chart1.Height - (end.Y - start.Y);
再考虑坐标转换,完整的代码就是
chart1.ChartAreas[0].AxisY.ScaleView.Position = chart1.ChartAreas[0].AxisY.ScaleView.ViewMaximum -
((double)(chart1.Height - end.Y + start.Y) * 100.0 / (double)chart1.Height - (double)chart1.ChartAreas[0].InnerPlotPosition.Y) / ypercent;
这样我们就可以实现chart图表的漫游功能啦。
下面给出漫游功能核心代码
Point start = new Point();
Point end = new Point();
private void chart1_MouseDown(object sender, MouseEventArgs e)
{
start.X = e.X;
start.Y = e.Y;
}
private void chart1_MouseUp(object sender, MouseEventArgs e)
{
double x_min = chart1.ChartAreas[0].AxisX.Minimum;
double y_min = chart1.ChartAreas[0].AxisY.Minimum;
double xpercent = (double)chart1.ChartAreas[0].InnerPlotPosition.Width / (chart1.ChartAreas[0].AxisX.ScaleView.ViewMaximum - chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum);
double ypercent = (double)chart1.ChartAreas[0].InnerPlotPosition.Height / (chart1.ChartAreas[0].AxisY.ScaleView.ViewMaximum - chart1.ChartAreas[0].AxisY.ScaleView.ViewMinimum);
//////计算Position的位置
chart1.ChartAreas[0].AxisX.ScaleView.Position = chart1.ChartAreas[0].AxisX.ScaleView.ViewMinimum +
((double)(start.X - end.X) * 100.0 / (double)chart1.Width - (double)chart1.ChartAreas[0].InnerPlotPosition.X) / xpercent;
if (chart1.ChartAreas[0].AxisX.ScaleView.Position < x_min)
chart1.ChartAreas[0].AxisX.ScaleView.Position = x_min;
chart1.ChartAreas[0].AxisY.ScaleView.Position = chart1.ChartAreas[0].AxisY.ScaleView.ViewMaximum -
((double)(chart1.Height - end.Y + start.Y) * 100.0 / (double)chart1.Height - (double)chart1.ChartAreas[0].InnerPlotPosition.Y) / ypercent;
if(chart1.ChartAreas[0].AxisY.ScaleView.Position < y_min)
chart1.ChartAreas[0].AxisY.ScaleView.Position = y_min;
}
这里我定义了两个参数,x_min和y_min,是当数据视图拖动到数据最左边甚至超过最左边的数据时,控制视图在最小值处,防止出现如下情况。
但是视图最大值处还不知道如何设置该参数,想用Position+ScrollBar的长度来表示,但是发现并没有参数能表示ScrollBar的长度,因此最右边我也就没有设置了,等以后想到了怎么解决再更新上来。或者有知道的小伙伴给我留言噢,谢谢。