Программный зум: .scaleTo(), .translateTo(), .translateBy()

Методы программного управления масштабированием в D3.js позволяют изменять трансформацию сцены без участия пользовательских событий, напрямую через API поведения zoom. Это особенно важно при создании интерактивных визуализаций, где требуется синхронизация масштаба, программная навигация по сцене, выделение областей данных и управление камерой в графах, картах и диаграммах.

Поведение zoom в D3 строится вокруг объекта d3.zoom, который управляет двумя ключевыми параметрами трансформации: масштабом (scale) и сдвигом (translate). Программные методы .scaleTo(), .translateTo() и .translateBy() воздействуют на текущее состояние zoom-поведения, эмулируя действия пользователя, но без событий мыши или жестов.


Каждое zoom-поведение в D3 хранит текущее состояние трансформации в виде объекта transform, включающего:

  • k — коэффициент масштабирования
  • x, y — смещение по осям

Изменение этих значений вручную не рекомендуется, так как zoom-логика управляет ими через систему событий и интерполяций. Вместо этого используются методы поведения, которые корректно обновляют состояние и инициируют соответствующие события.


.scaleTo() — установка масштаба относительно центра или точки

Метод .scaleTo() изменяет масштаб визуализации до заданного значения, учитывая текущую систему координат и опорную точку трансформации.

Сигнатура:

zoom.scaleTo(selection, k);

где:

  • selection — DOM-элемент, на который применено zoom-поведение
  • k — целевой коэффициент масштаба

Пример использования:

const svg = d3.select("svg");

const zoom = d3.zoom()
  .scaleExtent([0.5, 10])
  .on("zoom", (event) => {
    svg.select("g")
      .attr("transform", event.transform);
  });

svg.call(zoom);

// программное увеличение масштаба до 2
svg.transition()
  .duration(750)
  .call(zoom.scaleTo, 2);

Внутренне метод вычисляет новую трансформацию относительно текущего центра viewport, что делает переход визуально естественным.

Ключевые особенности:

  • масштабирование происходит относительно центра текущего viewport
  • учитываются ограничения scaleExtent
  • корректно синхронизируется с transition API

.translateTo() — центрирование на точке в координатах

Метод .translateTo() изменяет трансформацию таким образом, чтобы указанная точка в координатах данных оказалась в центре viewport или в заданной позиции.

Сигнатура:

zoom.translateTo(selection, x, y);

где:

  • x, y — координаты в системе данных, а не экрана

Пример:

svg.transition()
  .duration(750)
  .call(zoom.translateTo, 100, 200);

Этот метод полезен при навигации по большим графам или картам, когда необходимо сфокусироваться на узле или регионе.

Внутренний принцип работы:

  1. Берётся текущая трансформация
  2. Координаты точки преобразуются через инверсию текущего масштаба
  3. Вычисляется новый translate, чтобы точка оказалась в центре или якорной позиции

Практическое применение:

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

.translateBy() — относительное смещение сцены

Метод .translateBy() выполняет сдвиг текущей трансформации на заданное количество пикселей или единиц экранного пространства.

Сигнатура:

zoom.translateBy(selection, dx, dy);

где:

  • dx — смещение по оси X
  • dy — смещение по оси Y

Пример:

svg.transition()
  .duration(500)
  .call(zoom.translateBy, 50, -30);

Этот метод работает именно в экранных координатах, а не в координатах данных, что делает его удобным для пошаговой навигации.

Особенности:

  • не зависит от текущего масштаба напрямую
  • применяется как инкремент к существующему translate
  • используется для панорамирования сцены

Взаимодействие методов и порядок трансформаций

Методы программного zoom не изолированы друг от друга. Они изменяют единое состояние transform, поэтому порядок их вызова влияет на итоговую визуализацию.

Комбинация операций:

svg.transition()
  .duration(800)
  .call(zoom.scaleTo, 3)
  .transition()
  .call(zoom.translateTo, 400, 300);

В этом случае сначала изменяется масштаб, затем происходит центрирование с учётом нового масштаба.

При обратном порядке поведение будет иным: координаты центра будут вычисляться относительно предыдущего масштаба, что может сместить фокус.


Синхронизация с transition API

Все три метода поддерживают работу через selection.transition(), что позволяет создавать плавные анимации трансформаций.

Пример комплексной анимации:

function focusOnPoint(x, y, scale) {
  svg.transition()
    .duration(600)
    .call(zoom.scaleTo, scale)
    .transition()
    .duration(600)
    .call(zoom.translateTo, x, y);
}

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


Типичные сценарии применения

Программные методы zoom используются в следующих архитектурных паттернах визуализации:

  • управление камерой в force-directed графах
  • навигация по интерактивным картам
  • выделение кластеров данных
  • синхронизация нескольких представлений (linked views)
  • автоматическое центрирование при выборе элементов интерфейса

Внутренние ограничения и поведение

Zoom-поведение накладывает ряд ограничений, которые влияют на работу методов:

  • scaleExtent() ограничивает диапазон масштабирования
  • трансформации нормализуются перед применением
  • события zoom вызываются даже при программных изменениях
  • transition интерполирует между состояниями transform

При чрезмерно частых вызовах программного zoom возможна деградация производительности из-за постоянного пересчёта DOM-трансформаций и перерисовки SVG-слоя.


Координация с пользовательским вводом

Программные изменения zoom интегрируются в ту же систему событий, что и пользовательские действия. Это означает, что:

  • drag, wheel и touch могут перезаписывать программные трансформации
  • необходимо учитывать возможные гонки состояний
  • для сложных интерфейсов применяется блокировка взаимодействий во время анимаций

Пример защиты от конфликтов:

svg.on("wheel.zoom", null);

svg.transition()
  .duration(1000)
  .call(zoom.scaleTo, 4)
  .on("end", () => {
    svg.call(zoom);
  });

Координатная модель трансформаций

Все методы опираются на единую матрицу преобразования:

T(x, y, k) = translate(x, y) → scale(k)
  • scaleTo() изменяет компонент k
  • translateTo() вычисляет x, y относительно k
  • translateBy() корректирует x, y напрямую

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