MSCharts 自定义平移
MSCharts custom panning
我正在尝试在 MSCharts(Microsoft 图表控件)中制作我自己的自定义平移功能。我意识到有一个缩放和平移的扩展,但是它没有我想要的很多功能。这是我目前拥有的平移功能:
//handles mouse panning, will pan while mouse left click if held down..
private int prevx = 0;
private int prevy = 0;
private void Mouse_Up(object sender, MouseEventArgs e)
{
//reset previous x and y on mouse click up
if (e.Button == MouseButtons.Left)
{
prevx = 0;
prevy = 0;
}
}
private void Mouse_Move(object sender, MouseEventArgs e, Chart chart)
{
//if mouse was moved and mouse left click
if (e.Button == MouseButtons.Left)
{
//a scalar, not entirely sure how useful it is, only works for my viewport
double incr = 0.00130;
if (prevx != 0 && prevy != 0)
{
//find x and y difference in mouse movement
int diffx = e.X - prevx;
int diffy = e.Y - prevy;
//how much to increment x and y
double incrx = incr * Math.Abs(diffx);
double incry = incr * Math.Abs(diffy);
//get chart mins and maxs for both axes
double minX = chart.ChartAreas[0].AxisX.Minimum;
double maxX = chart.ChartAreas[0].AxisX.Maximum;
double minY = chart.ChartAreas[0].AxisY.Minimum;
double maxY = chart.ChartAreas[0].AxisY.Maximum;
if (diffx > 0 && diffy > 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("upleft");
}
else if (diffx < 0 && diffy > 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("upright");
}
else if (diffx > 0 && diffy < 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("bottom left");
}
else if (diffx < 0 && diffy < 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("bottomright");
}
else if (diffx > 0 && diffy == 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
//Console.WriteLine("right");
}
else if (diffx < 0 && diffy == 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
//Console.WriteLine("left");
}
else if (diffy > 0 && diffx == 0)
{
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("down");
}
else if (diffy < 0 && diffx == 0)
{
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("up");
}
}
prevx = e.X;
prevy = e.Y;
}
}
我注意到有一个类似的问题,虽然它是在我没有经验的 JavaFX 中。我设想的平移功能应该能够随着图形移动鼠标。因此,如果我单击某个点,向左拖动 50px,该点仍将直接位于我的鼠标下方。在我当前的视口中,这有效。但是,如果我将图形变小或变大,则一切都不起作用。当图形变小时,图形比我的鼠标移动得慢,当图形变大时,图形移动比我的鼠标快。
我知道我可能应该以某种方式将视口或图表宽度包括在计算中,但我真的不知道如何做。你们有这方面的经验吗?谢谢
您对 'scalar' 通过一个因子从像素计算值的方法表示怀疑是完全正确的。这永远行不通,原因不止一个..
但无论如何,正确的解决方案要简单得多。它利用轴转换函数之一在数据值和像素位置之间进行转换。 (还有一个可以转换百分比位置,顺便说一句..)
我存储了初始位置以避免鼠标移动时出现舍入错误:
private double prevXMax = 0;
private double prevXMin = 0;
private double prevYMax = 0;
private double prevYMin = 0;
private Point mDown = Point.Empty;
我们现在只需要 Mousedown
:
private void chart_MouseDown(object sender, MouseEventArgs e)
{
//store previous data
if (e.Button == MouseButtons.Left)
{
mDown = e.Location;
prevXMax = chart.ChartAreas[0].AxisX.Maximum;
prevXMin = chart.ChartAreas[0].AxisX.Minimum;
prevYMax = chart.ChartAreas[0].AxisY.Maximum;
prevYMin = chart.ChartAreas[0].AxisY.Minimum;
}
}
更简单MouseMove
:
private void chart_MouseMove(object sender, MouseEventArgs e)
{
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY;
//if mouse was moved and mouse left click
if (e.Button == MouseButtons.Left)
{
double x0 = ax.PixelPositionToValue(mDown.X);
double x1 = ax.PixelPositionToValue(e.X);
double y0 = ay.PixelPositionToValue(mDown.Y);
double y1 = ay.PixelPositionToValue(e.Y);
ax.Minimum = prevXMin + (x0 - x1);
ax.Maximum = prevXMax + (x0 - x1);
ay.Minimum = prevYMin + (y0 - y1);
ay.Maximum = prevYMax + (y0 - y1);
}
}
缩放计算的一个问题是您可能想要调整图表的大小;之后秤将不再工作。另一个是你必须去掉 ChartArea
和 InnerPlotPosition
之外的东西,即 Axis.Labels
、Titles
和 Legend
因为space 他们采取的不应按比例缩放..
请注意轴功能仅在 Paintxxx
或 Mousexxx
事件期间有效..
结果如下:
我正在尝试在 MSCharts(Microsoft 图表控件)中制作我自己的自定义平移功能。我意识到有一个缩放和平移的扩展,但是它没有我想要的很多功能。这是我目前拥有的平移功能:
//handles mouse panning, will pan while mouse left click if held down..
private int prevx = 0;
private int prevy = 0;
private void Mouse_Up(object sender, MouseEventArgs e)
{
//reset previous x and y on mouse click up
if (e.Button == MouseButtons.Left)
{
prevx = 0;
prevy = 0;
}
}
private void Mouse_Move(object sender, MouseEventArgs e, Chart chart)
{
//if mouse was moved and mouse left click
if (e.Button == MouseButtons.Left)
{
//a scalar, not entirely sure how useful it is, only works for my viewport
double incr = 0.00130;
if (prevx != 0 && prevy != 0)
{
//find x and y difference in mouse movement
int diffx = e.X - prevx;
int diffy = e.Y - prevy;
//how much to increment x and y
double incrx = incr * Math.Abs(diffx);
double incry = incr * Math.Abs(diffy);
//get chart mins and maxs for both axes
double minX = chart.ChartAreas[0].AxisX.Minimum;
double maxX = chart.ChartAreas[0].AxisX.Maximum;
double minY = chart.ChartAreas[0].AxisY.Minimum;
double maxY = chart.ChartAreas[0].AxisY.Maximum;
if (diffx > 0 && diffy > 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("upleft");
}
else if (diffx < 0 && diffy > 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("upright");
}
else if (diffx > 0 && diffy < 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("bottom left");
}
else if (diffx < 0 && diffy < 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("bottomright");
}
else if (diffx > 0 && diffy == 0)
{
chart.ChartAreas[0].AxisX.Minimum -= (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum -= (maxX - minX) * incrx;
//Console.WriteLine("right");
}
else if (diffx < 0 && diffy == 0)
{
chart.ChartAreas[0].AxisX.Minimum += (maxX - minX) * incrx;
chart.ChartAreas[0].AxisX.Maximum += (maxX - minX) * incrx;
//Console.WriteLine("left");
}
else if (diffy > 0 && diffx == 0)
{
chart.ChartAreas[0].AxisY.Minimum += (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum += (maxY - minY) * incry;
//Console.WriteLine("down");
}
else if (diffy < 0 && diffx == 0)
{
chart.ChartAreas[0].AxisY.Minimum -= (maxY - minY) * incry;
chart.ChartAreas[0].AxisY.Maximum -= (maxY - minY) * incry;
//Console.WriteLine("up");
}
}
prevx = e.X;
prevy = e.Y;
}
}
我注意到有一个类似的问题,虽然它是在我没有经验的 JavaFX 中。我设想的平移功能应该能够随着图形移动鼠标。因此,如果我单击某个点,向左拖动 50px,该点仍将直接位于我的鼠标下方。在我当前的视口中,这有效。但是,如果我将图形变小或变大,则一切都不起作用。当图形变小时,图形比我的鼠标移动得慢,当图形变大时,图形移动比我的鼠标快。
我知道我可能应该以某种方式将视口或图表宽度包括在计算中,但我真的不知道如何做。你们有这方面的经验吗?谢谢
您对 'scalar' 通过一个因子从像素计算值的方法表示怀疑是完全正确的。这永远行不通,原因不止一个..
但无论如何,正确的解决方案要简单得多。它利用轴转换函数之一在数据值和像素位置之间进行转换。 (还有一个可以转换百分比位置,顺便说一句..)
我存储了初始位置以避免鼠标移动时出现舍入错误:
private double prevXMax = 0;
private double prevXMin = 0;
private double prevYMax = 0;
private double prevYMin = 0;
private Point mDown = Point.Empty;
我们现在只需要 Mousedown
:
private void chart_MouseDown(object sender, MouseEventArgs e)
{
//store previous data
if (e.Button == MouseButtons.Left)
{
mDown = e.Location;
prevXMax = chart.ChartAreas[0].AxisX.Maximum;
prevXMin = chart.ChartAreas[0].AxisX.Minimum;
prevYMax = chart.ChartAreas[0].AxisY.Maximum;
prevYMin = chart.ChartAreas[0].AxisY.Minimum;
}
}
更简单MouseMove
:
private void chart_MouseMove(object sender, MouseEventArgs e)
{
Axis ax = chart.ChartAreas[0].AxisX;
Axis ay = chart.ChartAreas[0].AxisY;
//if mouse was moved and mouse left click
if (e.Button == MouseButtons.Left)
{
double x0 = ax.PixelPositionToValue(mDown.X);
double x1 = ax.PixelPositionToValue(e.X);
double y0 = ay.PixelPositionToValue(mDown.Y);
double y1 = ay.PixelPositionToValue(e.Y);
ax.Minimum = prevXMin + (x0 - x1);
ax.Maximum = prevXMax + (x0 - x1);
ay.Minimum = prevYMin + (y0 - y1);
ay.Maximum = prevYMax + (y0 - y1);
}
}
缩放计算的一个问题是您可能想要调整图表的大小;之后秤将不再工作。另一个是你必须去掉 ChartArea
和 InnerPlotPosition
之外的东西,即 Axis.Labels
、Titles
和 Legend
因为space 他们采取的不应按比例缩放..
请注意轴功能仅在 Paintxxx
或 Mousexxx
事件期间有效..
结果如下: