maxBounds

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

Основная идея заключается в том, что карта перестаёт быть «бесконечной плоскостью» и превращается в ограниченное пространство, строго привязанное к заданному прямоугольнику координат.


Базовая концепция maxBounds

Параметр maxBounds задаётся при инициализации карты и принимает объект типа LatLngBounds.

const map = L.map('map', {
    center: [55.751244, 37.618423],
    zoom: 10,
    maxBounds: L.latLngBounds(
        L.latLng(55.5, 37.2),
        L.latLng(56.0, 38.2)
    )
});

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


Поведение карты при достижении границ

При включённом maxBounds:

  • карта не позволяет пользователю увести центр за пределы области;
  • инерция панорамирования также ограничивается;
  • при перетаскивании карта «упирается» в границу и перестаёт двигаться в этом направлении;
  • масштабирование не нарушает ограничения, но может привести к частичному выходу видимой области за пределы bounds, если не настроены дополнительные параметры.

Динамическое изменение maxBounds

Границы можно изменять в процессе работы приложения.

const bounds = L.latLngBounds(
    [51.0, 36.0],
    [52.0, 38.0]
);

map.setMaxBounds(bounds);

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

Для снятия ограничений используется передача null:

map.setMaxBounds(null);

Взаимодействие с fitBounds

Метод fitBounds часто используется вместе с maxBounds, однако их поведение отличается по смыслу:

  • fitBounds изменяет центр и масштаб карты, чтобы вписать область;
  • maxBounds ограничивает свободу перемещения после этого.
map.fitBounds([
    [55.5, 37.2],
    [56.0, 38.2]
]);

Если fitBounds задаёт видимую область, то maxBounds фиксирует допустимую зону навигации, предотвращая выход за её пределы.


Влияние на масштабирование и zoom

maxBounds напрямую не блокирует zoom, но косвенно влияет на поведение карты:

  • при сильном увеличении карта может визуально выходить за границы;
  • при панорамировании после zoom происходит «прилипание» к допустимой области;
  • комбинация с minZoom и maxZoom позволяет жёстко контролировать навигацию.
const map = L.map('map', {
    maxBounds: L.latLngBounds([50, 35], [57, 40]),
    minZoom: 6,
    maxZoom: 14
});

Опция maxBoundsViscosity

Дополнительный параметр maxBoundsViscosity управляет «жёсткостью» ограничения. Он задаёт степень сопротивления при попытке выхода за пределы bounds.

const map = L.map('map', {
    maxBounds: L.latLngBounds([50, 35], [57, 40]),
    maxBoundsViscosity: 1.0
});

Значения:

  • 0.0 — ограничения фактически отсутствуют;
  • 1.0 — полная фиксация границ;
  • промежуточные значения создают эффект «резиновой» границы.

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


Применение в реальных сценариях

Географические приложения

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

map.setMaxBounds(L.latLngBounds(
    [41.0, 19.0],
    [52.5, 87.0]
));

Внутренние карты объектов

Для планов зданий, складов или торговых центров maxBounds фиксирует карту внутри схемы:

  • предотвращается пустое пространство;
  • упрощается навигация;
  • исключается потеря контекста.

Игровые и симуляционные карты

В игровых интерфейсах ограничение карты используется для создания «мира» с конечными границами:

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

Связь с тайловыми слоями

При использовании TileLayer важно, чтобы maxBounds соответствовал доступным тайлам:

const map = L.map('map', {
    maxBounds: L.latLngBounds([0, 0], [85, 180])
});

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);

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


Ограничения и особенности реализации

  • maxBounds ограничивает только навигацию, но не удаляет данные за пределами области;
  • при программном изменении центра через setView возможно временное «перескакивание» за границу;
  • некоторые взаимодействия (например, резкое изменение zoom) могут визуально нарушать ограничение до следующего события moveend;
  • поведение зависит от устройства ввода (мышь, тачскрин), так как инерция обрабатывается по-разному.

Комбинация с другими параметрами карты

На практике maxBounds редко используется изолированно. Обычно он работает вместе с:

  • minZoom и maxZoom — ограничение масштаба;
  • worldCopyJump — предотвращение копирования карты по горизонтали;
  • inertia — управление плавностью движения;
  • dragging — возможность отключения перетаскивания.

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


Динамическая реакция на события

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

map.on('zoomend', () => {
    const zoom = map.getZoom();

    if (zoom < 8) {
        map.setMaxBounds(L.latLngBounds([40, 30], [60, 50]));
    } else {
        map.setMaxBounds(L.latLngBounds([45, 35], [55, 45]));
    }
});

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


Поведение при выходе за границы программно

Если центр карты устанавливается вручную:

map.setView([70, 100], 5);

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


Геометрическая модель ограничения

maxBounds представляет собой прямоугольник в координатах широты и долготы:

  • северная граница — максимальная широта;
  • южная граница — минимальная широта;
  • восточная и западная границы — долготы.

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