MSCharts自定义平移 [英] MSCharts custom panning

查看:64
本文介绍了MSCharts自定义平移的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在MSCharts(Microsoft图表控件)中创建自己的自定义平移功能.我意识到有一个用于缩放和平移的扩展,但是它没有我想要的很多功能.这是我目前拥有的平移功能:

I'm trying to make my own custom panning feature in MSCharts (Microsoft Charting Controls). I realize there is an extension for zooming and panning, however it doesn't have a lot of the capabilities that I want it to have. Here is the panning function that I have currently:

//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,则该点仍将直接位于我的鼠标下方.在我当前的视口中,这可行.但是,如果我将图表缩小或放大,则将无法正常工作.当图形变小时,图形的移动速度比鼠标慢;当图形变大时,图形的移动速度比鼠标快.

I noticed there was a similar question, though it was in JavaFX, which I have no experience in. The panning feature that I envision is supposed to be able to move the mouse with the graph. So if I clicked on a certain point, dragged left 50px, that same point will still be directly under my mouse. In my current viewport, this works. However, if I make the graph smaller or larger, things don't work. When the graph becomes smaller, the graph moves slower than my mouse, and when the graph gets bigger, the graph moves faster than my mouse.

我知道我应该以某种方式将视口或统计图宽度包括在计算中,但是我真的不知道如何.你们中有人有经验吗?谢谢.

I know I should probably somehow include the viewport or chart width into the calculation, but I really just don't know how. Do any of you have experience with this? Thanks.

推荐答案

您完全正确地怀疑采用标量"方法从像素计算出因子值的正确方法.出于多种原因,这将永远无法工作.

You are quite right in doubting the 'scalar' approach to calculate values from pixels by a factor. This will never work and for more than one reason..

但是正确的解决方案却要简单得多.它利用轴转换功能之一在数据值和像素位置之间转换. (顺便说一下,还有一个可以转换为百分比位置的值).

But the correct solution is so much simpler anyway. It makes use of one of the axis conversion functions to convert between data values and pixel positions. (There is also one to convert to and from percent positions, btw..)

我存储初始位置是为了避免在鼠标移动过程中出现舍入错误:

I store the initial position to avoid rounding errors during the mouse move:

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);
    }
}

缩放计算的问题之一是您可能需要调整图表的大小.之后,秤将不再起作用.另一个是,您必须将ChartAreaInnerPlotPosition以外的东西取出,即Axis.LabelsTitlesLegend,因为它们占用的空间不应该缩放.

One of the problems with a scaling calculation is that you may want to resize the chart; after that the scale will no longer work. Another is that you would have to take out the stuff outside of the ChartArea, and the InnerPlotPosition, i.e. the Axis.Labels, Titles and the Legend since the space they take shouldn't be scaled..

请注意,轴功能仅在PaintxxxMousexxx事件期间有效..

Note the the axis functions are only valid during Paintxxx or Mousexxx events..

结果是:

这篇关于MSCharts自定义平移的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆