Прокрутка (pan) по осям

Прокрутка (pan) в Chart.js реализуется через дополнительный плагин, расширяющий стандартные возможности визуализации — обычно используется библиотека zoom/pan plugin (chartjs-plugin-zoom). Панорамирование позволяет перемещать область видимых данных по осям X и Y без изменения масштаба, что особенно важно при работе с плотными временными рядами, финансовыми графиками и телеметрией.

Механизм прокрутки опирается на взаимодействие с масштабами (scales) графика. Внутри Chart.js каждая ось представляет собой независимую систему преобразования данных в координаты. Панорамирование изменяет диапазон отображаемых значений (min и max) у соответствующих шкал.

Основной принцип:

  • ось не перерисовывается заново
  • изменяется только диапазон данных
  • график перерасчитывает видимую область

Это обеспечивает высокую производительность даже при больших наборах данных.

Подключение механизма pan

Функциональность панорамирования не входит в ядро Chart.js и подключается через плагин:

import { Chart } from 'chart.js';
import zoomPlugin from 'chartjs-plugin-zoom';

Chart.register(zoomPlugin);

После регистрации плагина становятся доступны параметры pan и zoom в конфигурации графика.

Базовая конфигурация панорамирования

Настройка выполняется в разделе options.plugins.zoom:

const config = {
  type: 'line',
  data: {
    labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
    datasets: [{
      label: 'Данные',
      data: [10, 30, 20, 50, 40]
    }]
  },
  options: {
    plugins: {
      zoom: {
        pan: {
          enabled: true,
          mode: 'x'
        }
      }
    }
  }
};

Ключевой параметр:

  • enabled — включает или отключает панорамирование
  • mode — определяет ось или оси взаимодействия

Режимы pan по осям

Панорамирование поддерживает несколько режимов работы:

mode: ‘x’

Перемещение только по горизонтальной оси. Используется для временных рядов, где X — время.

pan: {
  enabled: true,
  mode: 'x'
}

mode: ‘y’

Перемещение только по вертикальной оси. Применяется для анализа амплитудных изменений.

pan: {
  enabled: true,
  mode: 'y'
}

mode: ‘xy’

Свободное перемещение по обеим осям.

pan: {
  enabled: true,
  mode: 'xy'
}

Этот режим характерен для графиков рассеяния (scatter plots), где обе оси несут равнозначную нагрузку.

Управление типом взаимодействия

Панорамирование может быть привязано к разным типам пользовательского ввода:

drag (перетаскивание мышью)

Основной режим работы:

pan: {
  enabled: true,
  mode: 'x',
  modifierKey: null
}

modifierKey

Ограничение панорамирования по клавише-модификатору:

pan: {
  enabled: true,
  mode: 'xy',
  modifierKey: 'ctrl'
}

Поддерживаются значения:

  • ctrl
  • shift
  • alt
  • meta

Использование модификатора предотвращает случайное перемещение графика при обычном взаимодействии.

Чувствительность и скорость прокрутки

Параметр speed регулирует масштаб смещения при движении мыши:

pan: {
  enabled: true,
  mode: 'x',
  speed: 10
}
  • высокие значения ускоряют прокрутку
  • низкие обеспечивают более точное управление

В некоторых версиях плагина также применяется threshold, определяющий минимальное смещение для активации pan-жеста.

Ограничение области панорамирования

Для предотвращения выхода за пределы данных используются ограничения шкал.

rangeMin и rangeMax

options: {
  scales: {
    x: {
      min: 0,
      max: 100
    }
  }
}

При панорамировании Chart.js изменяет эти значения, но не позволяет выйти за заданные пределы, если включены ограничения.

limits в plugin-zoom

Более гибкий механизм:

zoom: {
  pan: {
    enabled: true,
    mode: 'x',
    limits: {
      x: {
        min: 0,
        max: 1000
      }
    }
  }
}

Это обеспечивает контроль над диапазоном даже при динамическом обновлении данных.

Синхронизация pan и zoom

Панорамирование часто используется совместно с масштабированием. В этом случае оба действия работают с одним состоянием шкал.

Пример конфигурации:

plugins: {
  zoom: {
    pan: {
      enabled: true,
      mode: 'x'
    },
    zoom: {
      wheel: {
        enabled: true
      },
      pinch: {
        enabled: true
      },
      mode: 'x'
    }
  }
}

Внутри происходит единое обновление scale.min и scale.max, что предотвращает рассинхронизацию состояния графика.

Программное управление панорамированием

Chart.js предоставляет API для управления состоянием через плагин:

resetZoom / reset

Сброс положения графика:

chart.resetZoom();

Фактически возвращает шкалы к исходным значениям.

manual update scales

Прямое изменение диапазона:

chart.options.scales.x.min = 20;
chart.options.scales.x.max = 80;
chart.update();

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

Панорамирование в реальном времени

При работе с потоковыми данными (streaming charts) pan может конфликтовать с автообновлением.

Типичный подход:

  • фиксация текущего диапазона
  • отключение авто-прокрутки при активном pan
  • восстановление следования за данными после сброса

Пример логики:

let isPanning = false;

pan: {
  enabled: true,
  mode: 'x',
  onPanStart: () => isPanning = true,
  onPanComplete: () => isPanning = false
}

При этом внешняя логика обновления данных проверяет флаг состояния.

Панорамирование и разные типы шкал

Категориальная шкала

При использовании категорий (labels) pan изменяет индексный диапазон:

  • смещение происходит по элементам массива
  • min/max интерпретируются как индексы

Линейная шкала

Для числовых данных:

  • pan изменяет реальные числовые границы
  • точность зависит от шага данных

Временная шкала

Для time-scale:

  • диапазон определяется временными метками
  • pan изменяет интервал времени просмотра

Производительность при панорамировании

Панорамирование оптимизировано за счёт:

  • частичного пересчёта scale
  • кэширования координат элементов
  • минимизации перерисовки canvas

Однако при больших датасетах возникают узкие места:

  • частые update() при кастомной логике
  • сложные анимации при каждом движении
  • одновременный zoom + pan без throttling

Решение — ограничение частоты обновлений и отключение анимаций:

options: {
  animation: false,
  responsiveAnimationDuration: 0
}

Интеграция с пользовательскими жестами

В дополнение к мыши pan может быть привязан к touch-событиям:

  • swipe по оси X → горизонтальное панорамирование
  • swipe по диагонали → xy mode

Это особенно важно для мобильных интерфейсов, где drag является основным способом навигации.

Особенности поведения при изменении данных

При обновлении dataset:

  • текущий pan-сдвиг сохраняется
  • если изменяется длина данных, возможна потеря синхронизации
  • при полной перезагрузке данных панорамирование сбрасывается

Рекомендуется контролировать состояние шкал вручную при динамических обновлениях.

Комбинация pan с несколькими осями

При наличии нескольких X или Y шкал:

scales: {
  x: { type: 'linear' },
  x2: { position: 'top' }
}

Панорамирование может быть:

  • синхронным (оба масштаба двигаются вместе)
  • независимым (каждая ось имеет свой pan)

Настройка задаётся через scale или mode с уточнением имени оси:

pan: {
  enabled: true,
  mode: 'x',
  scale: 'x2'
}

Ограничения и типичные конфигурационные ошибки

  • включение pan без регистрации плагина
  • конфликт модификаторов мыши с другими событиями
  • отсутствие ограничений leads to бесконечному смещению
  • использование xy mode без необходимости, приводящее к потере ориентации графика

Корректная настройка всегда требует явного определения mode, limits и стратегии взаимодействия с zoom.