Ограничения перемещения

В основе взаимодействия с картой и визуализациями в Deck.gl лежит управление состоянием представления (viewState). Именно через него контролируются перемещение, масштабирование и вращение сцены. Ограничение перемещения представляет собой набор механизмов, позволяющих фиксировать или сужать область навигации, предотвращая выход камеры за допустимые границы, а также управлять степенью свободы пользователя при исследовании данных.


Управление состоянием камеры через viewState

Ключевой объект взаимодействия — viewState, который описывает текущее положение и ориентацию камеры:

  • longitude, latitude — географические координаты центра сцены
  • zoom — уровень приближения
  • bearing — поворот карты вокруг вертикальной оси
  • pitch — наклон камеры
  • transitionDuration — длительность анимации перехода

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


Базовые ограничения координат

Наиболее распространённый тип ограничений — фиксация географических границ.

Ограничение широты и долготы

Контроль осуществляется через проверку значений longitude и latitude при обновлении состояния:

  • долгота обычно ограничивается диапазоном [-180, 180]
  • широта — диапазоном [-85.0511, 85.0511] (из-за проекции Web Mercator)

При попытке выхода за пределы значения «зажимаются» (clamp), предотвращая сдвиг карты в недопустимые области.

function clamp(value, min, max) {
  return Math.min(Math.max(value, min), max);
}

const nextViewState = {
  ...viewState,
  longitude: clamp(viewState.longitude, -180, 180),
  latitude: clamp(viewState.latitude, -85.0511, 85.0511)
};

Такой подход применяется как при ручной обработке onViewStateChange, так и в кастомных контроллерах.


Ограничение области просмотра (maxBounds)

Более гибкий механизм — ограничение рамками прямоугольной области карты. Он используется для предотвращения выхода пользователя за заданный регион.

Типичная реализация включает:

  • северную границу (north)
  • южную границу (south)
  • западную границу (west)
  • восточную границу (east)
const bounds = {
  north: 55.0,
  south: 50.0,
  west: 30.0,
  east: 40.0
};

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

function clampToBounds(longitude, latitude, bounds) {
  return {
    longitude: Math.min(Math.max(longitude, bounds.west), bounds.east),
    latitude: Math.min(Math.max(latitude, bounds.south), bounds.north)
  };
}

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


Ограничение масштаба (zoom constraints)

Контроль масштаба — один из ключевых элементов ограничения перемещения. Он определяет, насколько близко или далеко пользователь может приблизить сцену.

Основные параметры:

  • minZoom — минимальный уровень приближения
  • maxZoom — максимальный уровень приближения
const viewStateConstraints = {
  minZoom: 3,
  maxZoom: 14
};

При обновлении состояния:

viewState.zoom = Math.min(
  Math.max(viewState.zoom, viewStateConstraints.minZoom),
  viewStateConstraints.maxZoom
);

Ограничение zoom часто используется для:

  • предотвращения «проваливания» в пустую карту
  • защиты от чрезмерной детализации данных
  • стабилизации производительности

Ограничение вращения и наклона

Deck.gl позволяет управлять свободой вращения сцены через bearing и pitch.

Ограничение поворота (bearing)

  • bearing = 0 — север сверху
  • значения могут свободно изменяться, но часто фиксируются

Пример ограничения:

viewState.bearing = clamp(viewState.bearing, -45, 45);

Ограничение наклона (pitch)

Наклон камеры особенно важен для 3D-визуализаций. Чрезмерный наклон может привести к потере ориентации.

const pitchLimits = {
  minPitch: 0,
  maxPitch: 60
};

viewState.pitch = Math.min(
  Math.max(viewState.pitch, pitchLimits.minPitch),
  pitchLimits.maxPitch
);

Ограничение панорамирования

Панорамирование (drag) напрямую связано с изменением longitude и latitude. Ограничения здесь делятся на два типа:

  1. Жёсткое ограничение — запрещает выход за пределы области
  2. Мягкое ограничение — допускает выход с последующим возвратом

Жёсткая модель:

onViewStateChange: ({ viewState }) => {
  const constrained = clampToBounds(
    viewState.longitude,
    viewState.latitude,
    bounds
  );

  return {
    viewState: {
      ...viewState,
      ...constrained
    }
  };
};

Мягкая модель часто дополняется анимацией возврата к допустимой области, создавая эффект «резиновой границы».


Ограничение взаимодействий через Controller

Deck.gl использует систему контроллеров (controller), которые определяют допустимые жесты:

  • dragPan — перемещение карты
  • dragRotate — вращение
  • scrollZoom — масштабирование колесом
  • touchZoom — мультитач масштабирование
  • touchRotate — вращение жестами

Ограничения задаются через конфигурацию:

const controller = {
  dragPan: true,
  dragRotate: false,
  scrollZoom: {
    speed: 0.01
  },
  doubleClickZoom: false
};

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


Геометрические ограничения в 3D-сценах

В 3D-режиме ограничения перемещения становятся более сложными, так как добавляется ось Z и перспектива.

Типичные ограничения:

  • фиксированная высота камеры
  • ограничение угла обзора (field of view)
  • запрет пересечения с объектами сцены

Пример ограничения высоты:

viewState.zoom = clamp(viewState.zoom, 10, 16);

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


Ограничения через проекцию и CRS

Deck.gl опирается на Web Mercator, однако при использовании кастомных систем координат (CRS) ограничения перемещения задаются иначе.

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

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

Такие сценарии характерны для:

  • инженерных карт
  • indoor-навигации
  • научной визуализации

Анимационные ограничения и переходы

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

Используются параметры:

  • transitionDuration
  • transitionInterpolator
  • transitionEasing

Пример:

viewState: {
  longitude: constrained.longitude,
  latitude: constrained.latitude,
  zoom: constrained.zoom,
  transitionDuration: 400
}

Анимация делает ограничения визуально плавными, скрывая момент коррекции координат.


Приоритеты ограничений

При одновременном применении нескольких ограничений действует система приоритетов:

  1. географические bounds
  2. ограничения zoom
  3. ограничения pitch/bearing
  4. пользовательские фильтры
  5. контроллеры взаимодействия

Конфликты разрешаются последовательным применением clamp-операций, что обеспечивает предсказуемое поведение камеры.


Комбинированные стратегии ограничения

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

  • фиксированные географические границы
  • ограниченный zoom диапазон
  • отключённое вращение
  • частично разрешённое панорамирование
  • плавные возвраты в допустимую область

Такая конфигурация обеспечивает баланс между свободой навигации и контролем над визуализацией данных, особенно в аналитических и картографических системах на базе Deck.gl.