Рисование оси над точкой и предотвращение выделения в DataVisualization.Charting - PullRequest
0 голосов
/ 17 сентября 2018

Я использую круговой маркер для указания положения точек данных. Когда точки нарисованы на оси, я не могу выбрать их (используя HitTest) ... но я могу выбрать их, когда они нарисованы где-либо еще на графике. Невыбираемые точки, кажется, рисуют под оси. Если я увеличу маркеры, то смогу выбрать точки на оси, щелкнув по краю круга.

Есть ли способ заставить маркеры рисовать поверх оси (если это проблема!)?

enter image description here

1 Ответ

0 голосов
/ 17 сентября 2018

Это действительно хороший вопрос.

Проблема действительно реальна. Я не знаю простого решения.

  • Вот один из возможных способов:

Вы можете изменить X, в котором вы тестируете, когда обнаружите, что вы нажали Axis или AxisLabel или TickMark.Вычислите положение , отраженное по оси ond смещение по ширине, и повторите тест.

Для этого вам нужно знать положение оси в пикселях и ее ширину.

Последний - axis.Linewidth.Для первого используйте функцию оси ax.ValueToPixelPosition.Он принимает значение x в позиции оси y.Это будет либо минимум оси X (если он задан), либо 0, либо какое-то автоматическое значение, в зависимости от ваших данных.

Это действительно улучшает ситуацию, хотя я обнаружил, что TickMarks по-прежнему стремятся попасть вкстати, не уверен почему.

Пользователи будут любить, если точка мыши действительно близко, будет расти, пока они не уйдут снова.Вы можете использовать обратную функцию PixelPositionToValue и некоторые Linq, чтобы найти ближайшую точку.

Обновление:

  • Фактически, последняя идея может быть реализована какальтернативный обходной путь.

Вот пример функции для поиска ближайшей точки, возможно, в событии MouseMove или, возможно, после того, как HitTest достигнет оси или элемента оси ..:

DataPoint GetNearestPoint(Series s, ChartArea ca, Point pt)
{
    int limit = s.MarkerSize * 4;  // pick a suitable distance!

    Axis ay = ca.AxisY;
    Axis ax = ca.AxisX;

    var mins = s.Points.Cast<DataPoint>().Select((x, index) =>
        new
        {
            val = Math.Abs(pt.Y - (int)ay.ValueToPixelPosition(x.YValues[0]))
                    +  Math.Abs(pt.X - (int)ax.ValueToPixelPosition(x.XValue)),
            ix = index
        });

    var min = mins.Where(x => x.val == mins.Min(v => v.val)).Select(x => x.ix).First();
    if (mins.ElementAt(min).val > limit) return null;
    else return s.Points[min];
}

Вот как я это называю после создания переменной уровня класса:

DataPoint lastHit = null;

Она окрашивает ближайшую точку, когда курсор находится достаточно близко ..:

    var nearest = GetNearestPoint(someSeries, someChart.ChartAreas[0], e.Location);
    if (lastHit != null) lastHit.MarkerColor =  someSeries.Color;
    if (nearest != null)
    {
        lastHit = nearest;
        nearest.MarkerColor = Color.Red;
    } 

Увеличение MarkerSize происходит, если курс такой же простой (по крайней мере, если ваш ChartType не равен Bubble, как у меня; -)

enter image description here

  • Еще один обходной путь будет довольно грязным: вы можете добавить дополнительные ChartArea и , наложив их точно на по сравнению с исходным.Вам нужно будет получить ElementPositions оригинала, а также InnerPlotPosition, а затем использовать их для наложения.Теперь вы можете переместить серию во 2-й, верхний ChartArea, а также отключить Axis и т. Д. HitTest должен работать, как и ожидалось.Но позиции необходимо корректировать при каждом изменении размера.
...