Как отобразить информацию о ближайшей точке данных линейного графика, наведя указатель мыши на область графика - PullRequest
1 голос
/ 03 октября 2019

Я собираюсь нарисовать диаграмму, используя c # в приложении Windows Form. Мне нужно нарисовать круг на линейном графике и показать это значение точки данных на метке, которая является ближайшей точкой данных от оси x указателя мыши, когда мышь перемещается над областью диаграммы.

Я пишукод следующим образом ......

private void Chart1_MouseMove(object sender, MouseEventArgs e)
    {
        HitTestResult result = Chart1.HitTest(e.X, e.Y);

        DataPoint nearestPoint = null;

        if (prevPosition!=null)
        {

            Chart1.Series[0].Points[prevPosition.PointIndex].MarkerStyle = MarkerStyle.None;


        }


        if (result.ChartElementType == ChartElementType.DataPoint)
        {


            string xValue = DateTime.FromOADate(Chart1.Series[0].Points[result.PointIndex].XValue).ToString("yyyy/MM/dd");
            string yValue = Convert.ToString(Chart1.Series[0].Points[result.PointIndex].YValues[0]);

            Chart1.Series[0].Points[result.PointIndex].MarkerStyle = MarkerStyle.Circle;
            Chart1.Series[0].Points[result.PointIndex].MarkerSize = 7;
            Chart1.Series[0].Points[result.PointIndex].MarkerColor = Color.Green;

            label1.Text = "Date:" + xValue;
            label2.Text = "Price:" + yValue;
            prevPosition = result;

        }

Но этот код показывает значение и соответствующий кружок над линией, когда мышь приближается к изображенной линии. Когда мышь находится далеко от линии, но находится внутри области графика, она не показывает окружность и значение. Мне нужно нарисовать кружок над точкой, ближайшей к оси X указателя мыши, и показать эти данные на метке

1 Ответ

0 голосов
/ 03 октября 2019

Вы можете найти ближайшую точку, измеряющую только значения x или y, или измеряющую абсолютные расстояния. Или вы можете просто вывести значения под курсором мыши, независимо от точек. Для этого последнего см. Здесь !

Для каждого из первых трех вариантов это должно помочь:

Переменные уровня класса, используемые для установки и сброса цветов ..:

DataPoint dpXaxis = null;
DataPoint dpYaxis = null;
DataPoint dpAbs = null;

И список точек для сохранения местоположения пикселей всех точек:

List<Point> pixPoints = null;

Событие MouseMove:

private void chart_MouseMove(object sender, MouseEventArgs e)
{
    ChartArea ca = chart.ChartAreas[0];
    Axis ax = ca.AxisX;
    Axis ay = ca.AxisY;
    Series s = chart.Series[0];

    if (!s.Points.Any()) return; // no data, no action!

    // option 1:
    // the values at the mouse pointer:
    double valx = ax.PixelPositionToValue(e.X);
    double valy = ay.PixelPositionToValue(e.Y);

    // the deltas on the x-axis (with index):
    var ix = s.Points.Select((x, i) => new {delta = Math.Abs(x.XValue - valx), i})
                            .OrderBy(x => x.delta).First().i;
    var dpx = s.Points[ix];

    // option 2:
    // the deltas on the y-axis (with index):
    var iy = s.Points.Select((x, i) => 
                      new {delta = Math.Abs(x.YValues[0] - valy), i })
                     .OrderBy(x => x.delta).First().i;
    var dpy = s.Points[iy];

    // option 3:
    // the absolute distances (with index):
    var ind = pixPoints.Select((x, i) =>
        new { delta = Math.Abs(x.X - e.X) + Math.Abs(x.Y - e.Y), i}).
        OrderBy(x => x.delta).First().i;
    // find index of smallest delta
    var dpca = s.Points[ind];


    // set/reset colors
    if (dpXaxis != null) dpXaxis.Color = s.Color;
    dpXaxis = dpx;
    dpXaxis.Color = Color.LawnGreen;

    // set/reset colors
    if (dpYaxis != null) dpYaxis.Color = s.Color;
    dpYaxis = dpy;
    dpYaxis.Color = Color.Cyan;

    if (dpAbs != null) dpAbs.Color = s.Color;
    dpAbs = dpca;
    dpAbs.Color = Color.Red;
}

Чтобы найти ближайшую точкув обоих направлениях вам нужно будет либо включить шкалы осей, либо, возможно, проще, создать List<PointF> из DataPoints, который будет содержать положения точек в пикселях. Для этого используйте функции обратной оси. Затем я вычисляю дельты таким же образом, как и в Linq выше.

Список заполняется / обновляется примерно так:

List<Point> getPixPoints(Series s, ChartArea ca)
{
    List<Point> points = new List<Point>();
    foreach (DataPoint dp in s.Points)
    {
        points.Add(new Point(
            (int)ca.AxisX.ValueToPixelPosition(dp.XValue),
            (int)ca.AxisY.ValueToPixelPosition(dp.YValues[0])  ));
    }
    return points;
}

Давайте посмотрим на это в работе:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...