Home > Net >  Highlight winforms MS Chart line on hover
Highlight winforms MS Chart line on hover

Time:11-25

I'm trying to use MS Chart with custom controls. My purpose is to:

  • Highlight only a segment of the line that connects two neighboring points on mouse hover over that piece
  • Find indexes of those two neighboring points (I need that for being able to drag that line by moving two points simultaneously)

Kind of illustration: enter image description hereenter image description here

For now I can detect a hover over a line on the chart by using the approach described here. But I'm stuck in finding indexes or at least coordinates of those two points.

CodePudding user response:

So the original idea from this question was to find nearest points by x (assuming that all the series has x-values are indeed steadily increasing) and then calculate y-value. But I have a little improved that and added support for completely vertical lines. So here is my code for capturing the needed line:

 private static GrippedLine? LineHitTest(Series series, double xPos, double yPos, Axis xAxis, Axis yAxis)
    {
        double xPixelPos = xAxis.PixelPositionToValue(xPos);
        double yPixelPos = yAxis.PixelPositionToValue(yPos);
        DataPoint[] neighbors = new DataPoint[2];
        neighbors[0] = series.Points.Last(x => x.XValue <= xPixelPos);
        neighbors[1] = series.Points.First(x => x.XValue >= xPixelPos);

        DataPoint[] verticalMates;
        foreach (DataPoint neighbor in neighbors)
        {
            if (Math.Abs(neighbor.XValue - xPixelPos) < LINE_GRIP_REGION)
            {
                verticalMates = series.Points.FindAllByValue(neighbor.XValue, "X").ToArray();
                if (verticalMates.Length > 1)
                {
                    if (verticalMates.Length > 2)
                    {
                        if (verticalMates[0].YValues[0] < verticalMates[verticalMates.Length - 1].YValues[0])
                        {
                            neighbors[0] = verticalMates.LastOrDefault(y => y.YValues[0] < yPixelPos);
                            neighbors[1] = verticalMates.FirstOrDefault(y => y.YValues[0] >= yPixelPos);
                        }
                        else
                        {
                            neighbors[0] = verticalMates.LastOrDefault(y => y.YValues[0] > yPixelPos);
                            neighbors[1] = verticalMates.FirstOrDefault(y => y.YValues[0] <= yPixelPos);
                        }
                    }
                    else
                    {
                        neighbors[0] = verticalMates[0];
                        neighbors[1] = verticalMates[1];
                    }
                    break;
                }
            }
        }

        double x0 = xAxis.ValueToPixelPosition(neighbors[0].XValue);
        double y0 = yAxis.ValueToPixelPosition(neighbors[0].YValues[0]);

        double x1 = xAxis.ValueToPixelPosition(neighbors[1].XValue);
        double y1 = yAxis.ValueToPixelPosition(neighbors[1].YValues[0]);

        double Yinterpolated = y0   (y1 - y0) * (xPos - x0) / (x1 - x0);

        int[] linePoints = new int[2];
        // if mouse Y position is near the calculated OR the line is vertical
        if (Math.Abs(Yinterpolated - yPos) < LINE_GRIP_REGION || neighbors[0].XValue == neighbors[1].XValue)
        {
            linePoints[0] = series.Points.IndexOf(neighbors[0]);
            linePoints[1] = series.Points.IndexOf(neighbors[1]);

        }
        else
        {
            return null;
        }
        return new GrippedLine()
        {
            startLinePointIndex = linePoints[0],
            endLinePointIndex = linePoints[1],
            x0Correction = neighbors[0].XValue - xPixelPos,
            y0Correction = neighbors[0].YValues[0] - yPixelPos,
            x1Correction = neighbors[1].XValue - xPixelPos,
            y1Correction = neighbors[1].YValues[0] - yPixelPos
        };
    }
  • Related