Вот решение, которое будет увеличивать в 2 раза с каждым кликом.
В качестве диапазона значений, которые будут видны в увеличенном виде, используется переменная span
.
Также перемещает позицию щелчка к следующей ближайшей DataPoint
. Вы можете удалить это, чтобы разрешить увеличение позиций между DataPoints
.
Давайте посмотрим на это в действии:
Обратите внимание, что первая проблема с вашим кодом - это используемые вами координаты.
Это три (!) Системы координат в MSChart
:
- Пикселей как в
MouseClick
- Значения как в
Axis
Значения
- Позиции как в
ElementPositions
, т.е. проценты , относящиеся к следующему более высокому контейнеру
Ваша основная проблема в том, что вы смешиваете пиксели со значениями , что приводит к хаосу.
Вам необходимо преобразовать пикселей в значения, как показано в коде.
Вот переменные, которые я использую:
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
Теперь код клика с преобразованием:
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
}
Наконец код для кнопки увеличения:
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);
}
Несколько заметок:
- Функции преобразования доступны только после того, как график закончил макет.
- Я только увеличиваю ось X и только увеличиваю. Добавление масштабирования по оси Y и уменьшение масштаба должно быть простым ..
- Изменение скорости или размера шага - тоже не ракетостроение. Обратите внимание, что шаги должны быть фактор , чтобы обеспечить хороший пользовательский опыт. Если вы добавите (вместо умножения), масштабирование не будет выглядеть линейным, но будет становиться быстрее или медленнее с каждым шагом.
- Конечно, маркеры и визуализация нажатых точек не являются обязательными и могут плохо работать с вашей диаграммой.
- Я использую
PointF
для хранения значений, по которым щелкнули. Обычно floats
подойдет; это может быть не так, если значения DateTime
, хотя. В таком случае используйте два doubles
!
- Обратите внимание, как я поместил
Axis
в переменные . Я обычно делаю то же самое с Series
и ChartAreas
. Намного проще писать, читать, и я думаю, что даже (немного) быстрее запустить ...