C# chart以鼠标所在位置为中心进行缩放
程序员文章站
2022-06-11 11:11:21
...
以前都用labview做一些软件,但给出去总是会遇到版本,安装包过大等一些问题,于是想自学C#,记录一下使用过程中遇到的一些问题和解决措施,便于日后回顾。
在这个项目中需要绘制折线图,由于数据比较大,需要对图表进行缩放操作,以鼠标为中心对图表进行缩放,在网上查找了一些资料没找到我想要的,于是自己想了一个解决方案,可以基本实现,但略显繁琐,由于刚开始学习C#,对一些操作不太了解,若以后遇到了更简单的解决方案,会再进行补充,目前只能用点糙方法了。
思路只有一个,就是保持鼠标所在位置与图表两端的比例不变,这样便可保持鼠标所在位置的数据点不会改变,如下图,以b点为中心进行放大操作,设置好放大比例,先找到X1位置,然后根据比列关系计算出X2位置,便可保持b点位置不变进行放大,缩小与放大思路一致,但会存在边界问题,处理略微复杂一点。labview中可以直接设置图表显示的最小值和最大值,C#这两个为只读属性,只好通过设置缩放视图的大小和起始位置来实现了。
void chart_MouseWheel(object sender, MouseEventArgs e)
{
Chart chart = (Chart)sender;
double zoomfactor = 2; //设置缩放比例
double xstartpoint = chart.ChartAreas[0].AxisX.ScaleView.ViewMinimum; //获取当前x轴最小坐标
double xendpoint = chart.ChartAreas[0].AxisX.ScaleView.ViewMaximum; //获取当前x轴最大坐标
double xmouseponit = chart.ChartAreas[0].AxisX.PixelPositionToValue(e.X); //获取鼠标在chart中x坐标
double xratio = (xendpoint - xmouseponit) / (xmouseponit - xstartpoint); //计算当前鼠标基于坐标两侧的比值,后续放大缩小时保持比例不变
if (e.Delta > 0) //滚轮上滑放大
{
if (chart.ChartAreas[0].AxisX.ScaleView.Size > 5) //缩放视图不小于5
{
if ((xmouseponit >= chart.ChartAreas[0].AxisX.ScaleView.ViewMinimum) && (xmouseponit <= chart.ChartAreas[0].AxisX.ScaleView.ViewMaximum)) //判断鼠标位置不在x轴两侧边沿
{
double xspmovepoints = Math.Round((xmouseponit - xstartpoint) * (zoomfactor - 1) / zoomfactor, 1); //计算x轴起点需要右移距离,保留一位小数
double xepmovepoints = Math.Round(xendpoint - xmouseponit - xratio * (xmouseponit - xstartpoint - xspmovepoints), 1); //计算x轴末端左移距离,保留一位小数
double viewsizechange = xspmovepoints + xepmovepoints; //计算x轴缩放视图缩小变化尺寸
chart.ChartAreas[0].AxisX.ScaleView.Size -= viewsizechange; //设置x轴缩放视图大小
chart.ChartAreas[0].AxisX.ScaleView.Position += xspmovepoints; //设置x轴缩放视图起点,右移保持鼠标中心点
}
}
}
else //滚轮下滑缩小
{
if (chart.ChartAreas[0].AxisX.ScaleView.Size < chart.ChartAreas[0].AxisX.Maximum)
{
double xspmovepoints = Math.Round((zoomfactor - 1) * (xmouseponit - xstartpoint), 1); //计算x轴起点需要左移距离
double xepmovepoints = Math.Round((zoomfactor - 1) * (xendpoint - xmouseponit), 1); //计算x轴末端右移距离
if (chart.ChartAreas[0].AxisX.ScaleView.Size + xspmovepoints + xepmovepoints < chart.ChartAreas[0].AxisX.Maximum) //判断缩放视图尺寸是否超过曲线尺寸
{
if ((xstartpoint - xspmovepoints <= 0) || (xepmovepoints + xendpoint >= chart.ChartAreas[0].AxisX.Maximum)) //判断缩放值是否达到曲线边界
{
if (xstartpoint - xspmovepoints <= 0) //缩放视图起点小于等于0
{
xspmovepoints = xstartpoint;
chart.ChartAreas[0].AxisX.ScaleView.Position = 0; //缩放视图起点设为0
}
else
chart.ChartAreas[0].AxisX.ScaleView.Position -= xspmovepoints; //缩放视图起点大于0,按比例缩放
if (xepmovepoints + xendpoint >= chart.ChartAreas[0].AxisX.Maximum) //缩放视图终点大于曲线最大值
chart.ChartAreas[0].AxisX.ScaleView.Size = chart.ChartAreas[0].AxisX.Maximum - chart.ChartAreas[0].AxisX.ScaleView.Position; //设置缩放视图尺寸=曲线最大值-视图起点值
else
{
double viewsizechange = xspmovepoints + xepmovepoints; //计算x轴缩放视图缩小变化尺寸
chart.ChartAreas[0].AxisX.ScaleView.Size += viewsizechange; //按比例缩放视图大小
}
}
else
{
double viewsizechange = xspmovepoints + xepmovepoints; //计算x轴缩放视图缩小变化尺寸
chart.ChartAreas[0].AxisX.ScaleView.Size += viewsizechange; //按比例缩放视图大小
chart.ChartAreas[0].AxisX.ScaleView.Position -= xspmovepoints; //按比例缩放视图大小
}
}
else
{
chart.ChartAreas[0].AxisX.ScaleView.Size = chart.ChartAreas[0].AxisX.Maximum;
chart.ChartAreas[0].AxisX.ScaleView.Position = 0;
}
}
}
}
最后实现的效果还是可以接受的,基本可以保证缩放时鼠标所在点位置固定,缩放比列可调节。谨以此篇文章记录我学习C#的开始。