Это действительно хороший вопрос.
Проблема действительно реальна. Я не знаю простого решения.
- Вот один из возможных способов:
Вы можете изменить 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
, как у меня; -)
- Еще один обходной путь будет довольно грязным: вы можете добавить дополнительные ChartArea и , наложив их точно на по сравнению с исходным.Вам нужно будет получить
ElementPositions
оригинала, а также InnerPlotPosition
, а затем использовать их для наложения.Теперь вы можете переместить серию во 2-й, верхний ChartArea
, а также отключить Axis
и т. Д. HitTest
должен работать, как и ожидалось.Но позиции необходимо корректировать при каждом изменении размера.