Search code examples
c#mschartzooming

zoom in zoom out from a point mschart


enter image description here How to zoom from a point for example zoom from point 300 to 500 axisX and 50 to 100 AxisY step by step

Current location

private void chart1_MouseClick(object sender, MouseEventArgs e) {

        lastPoint = e.Location;
}

Zooming X And Y

 private void btnZoomXY_Click(object sender, EventArgs e)
    {



            step = (int)(chart1.ChartAreas["ChartArea1"].AxisX.Maximum - lastPoint.X ) / 20;
        if (zoomx > chart1.ChartAreas["ChartArea1"].AxisX.Maximum)
        {
            zoomx -= step;

        }
        else
            zoomx += step;
        this.chart1.ChartAreas["ChartArea1"].AxisX.ScaleView.Zoom(lastPoint.X+ zoomx, this.chart1.ChartAreas["ChartArea1"].AxisX.Maximum - zoomx);


        if (Mode == SpectometrMode.Absorbance)
        {
            step1 = 0.2f;
        }
        else
             step1 = (int)(chart1.ChartAreas["ChartArea1"].AxisY.Maximum - lastPoint.Y) / 20;
        if (zoomY > chart1.ChartAreas["ChartArea1"].AxisY.Maximum)
        {
            zoomY -= step1;

        }
        else
            zoomY += step1;
        this.chart1.ChartAreas["ChartArea1"].AxisY.ScaleView.Zoom(lastPoint.Y+ zoomY, this.chart1.ChartAreas["ChartArea1"].AxisY.Maximum - zoomY);




        chart1.ChartAreas[0].AxisX.LabelStyle.Format = "{0}";
    }

@taW


Solution

  • Here is a solution that will zoom in 2x with each click.

    It uses a variable span as the range of values that will be visible in the zoomed view.

    It also moves the clicked position to the next closest DataPoint. You may remove this to allow zooming in on positions between DataPoints.

    Let's see it in action:

    enter image description here

    Note that the first issue with your code is the coordinates you use.

    These are three (!) coordinate systems in MSChart:

    • Pixels as in MouseClick
    • Values as in Axis values
    • Positions as in ElementPositions i.e. percentages related to the next higher container

    Your main issue is that you mix pixels with values which will result in chaos.

    You need to convert the pixels to values as in the code shown.

    Here are the variables I use:

    double span = 0;                     // axis range in values
    Point lastPoint = Point.Empty;       // the clicked position
    PointF clickedValues = PointF.Empty; // the values of the clicked positiom
    DataPoint closePoint = null;         // the next closest DataPoint
    

    Now the click code with the conversion:

    private void chart1_MouseClick(object sender, MouseEventArgs e)
    {
        lastPoint = e.Location;
        Axis ax = chart1.ChartAreas[0].AxisX;
        Axis ay = chart1.ChartAreas[0].AxisY;
    
        if (closePoint != null) closePoint.MarkerColor = chart1.Series[0].MarkerColor;
    
        clickedValues = new PointF((float)ax.PixelPositionToValue(lastPoint.X),
                                   (float)ay.PixelPositionToValue(lastPoint.Y));
    
        closePoint = chart1.Series[0].Points.Where(x => x.XValue >= clickedValues .X).First();
        closePoint.MarkerColor = Color.Red;  // optionally mark the point
    
        // optionally move clicked position to actual datapoint
        nextDPoint = new PointF((float)closePoint.XValue, (float)closePoint.YValues[0]);
    
        span = ax.Maximum - ax.Minimum;  // the full range of values
    }
    

    Finally the code for the zoom-in button:

    private void button1_Click(object sender, EventArgs e)
    {
        span /= 2;  // zoom in 2x each time
        Axis ax = chart1.ChartAreas[0].AxisX;
        Axis ay = chart1.ChartAreas[0].AxisY;
        ax.ScaleView.Zoom(nextDPoint.X - span, nextDPoint.X + span);
    }
    

    A few notes:

    • The conversion functions are only available after the chart has finished layout.
    • I only zoom the x-axis and I only zoom-in. Adding y-axis zoom and zooming-out should be simple..
    • changing the speed or step size is also not rocket science. Note that the steps should be a factor to allow a good user experience. If you add (instead of multiply) the zooming will not look linear but will either get faster or slower with each step..
    • Of course the markers and the visualization of the clicked points is optional and may not work well with your chart.
    • I use a PointF to store the clicked values. Usually floats will do; this may not be true if the values are DateTime, though. In such a case do use two doubles!
    • Note how I put the Axis into variables. I usually do the same with Series and ChartAreas. Much easier to write, read and I think even (a little) faster to run.. .