Класс Bounds

Класс L.LatLngBounds представляет прямоугольную географическую область на карте, ограниченную юго-западной и северо-восточной точками. Внутри Leaflet этот класс используется для вычисления видимой области карты, подгонки отображения под набор объектов, проверки пересечений и множества пространственных операций.

Параллельно существует класс L.Bounds, который работает в пиксельных координатах (L.Point) и применяется внутри системы рендеринга тайлов, слоёв и DOM-позиционирования. Оба класса концептуально схожи, но оперируют разными системами координат.


L.LatLngBounds описывает прямоугольник на поверхности Земли через две крайние точки:

  • юго-западную (SouthWest)
  • северо-восточную (NorthEast)

Эти точки определяют минимальные и максимальные значения широты и долготы.

Создание границ

Базовая форма создания:

const bounds = L.latLngBounds(
  L.latLng(55.70, 37.50), // SW
  L.latLng(55.80, 37.70)  // NE
);

Возможен альтернативный вариант через массив координат:

const bounds = L.latLngBounds([
  [55.70, 37.50],
  [55.75, 37.60],
  [55.80, 37.70]
]);

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


Расширение границ (extend)

Метод extend увеличивает область, включая новые точки или другие границы.

Добавление точки

bounds.extend([55.85, 37.65]);

Объединение с другими границами

const b1 = L.latLngBounds([55.70, 37.50], [55.75, 37.60]);
const b2 = L.latLngBounds([55.76, 37.61], [55.80, 37.70]);

b1.extend(b2);

После выполнения b1 охватывает обе области.


Получение крайних точек

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

bounds.getSouthWest();
bounds.getNorthEast();
bounds.getNorthWest();
bounds.getSouthEast();

Каждый метод возвращает объект LatLng.


Центр границ

Метод getCenter() вычисляет географический центр прямоугольника:

const center = bounds.getCenter();

Это полезно для центрирования карты или размещения маркера.


Проверка вхождения точек

Метод contains определяет, находится ли точка внутри границ:

bounds.contains([55.76, 37.62]);

Возвращает true или false.


Пересечение границ

Метод intersects проверяет, пересекаются ли две области:

const a = L.latLngBounds([55.70, 37.50], [55.75, 37.60]);
const b = L.latLngBounds([55.74, 37.59], [55.80, 37.70]);

a.intersects(b);

Используется при фильтрации видимых объектов.


Проверка валидности

Границы считаются валидными только если определены обе точки:

bounds.isValid();

Если границы были созданы пустыми или не расширены — результат будет false.


Расширение с отступом (pad)

Метод pad увеличивает границы на процент от их размера:

const padded = bounds.pad(0.2);

Значение 0.2 увеличивает область на 20% во всех направлениях. Это часто используется для подгрузки объектов за пределами экрана.


Привязка карты к границам

Одна из ключевых возможностей Leaflet — автоматическое позиционирование карты под область:

map.fitBounds(bounds);

Этот метод масштабирует и центрирует карту так, чтобы вся область была видна.

Дополнительные параметры:

map.fitBounds(bounds, {
  padding: [20, 20],
  maxZoom: 15
});

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

Границы могут использоваться как ограничитель:

map.setMaxBounds(bounds);

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


Внутренние особенности работы

LatLngBounds всегда нормализует координаты:

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

При пересечении антимеридиана (±180° долготы) поведение требует особого внимания, так как долготы “перепрыгивают” через границу диапазона.


Пустые и динамические границы

Часто создаются пустые границы, которые затем расширяются:

const bounds = L.latLngBounds();

points.forEach(p => bounds.extend(p));

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


Работа с массивами объектов

При наличии набора маркеров:

const bounds = L.latLngBounds(
  markers.map(m => m.getLatLng())
);

map.fitBounds(bounds);

Или динамическое расширение:

markers.forEach(m => bounds.extend(m.getLatLng()));

Сравнение и логические операции

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

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

Пример фильтрации:

const visible = points.filter(p =>
  bounds.contains(p.latlng)
);

L.Bounds: пиксельные границы

L.Bounds используется внутри системы рендеринга и работает с L.Point.

Создание

const b = new L.Bounds(
  new L.Point(0, 0),
  new L.Point(256, 256)
);

Основные методы L.Bounds

extend

Расширяет область:

b.extend(new L.Point(300, 100));

getSize

Возвращает размер прямоугольника:

b.getSize(); // Point(width, height)

getCenter

Центр в пиксельных координатах:

b.getCenter();

contains

Проверка точки:

b.contains(new L.Point(150, 150));

Пересечение пиксельных областей

b1.intersects(b2);

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


Применение в системе тайлов

При загрузке карты каждый тайл имеет собственные пиксельные границы. L.Bounds помогает:

  • определять видимые тайлы
  • отбрасывать невидимые элементы
  • оптимизировать перерисовку

Связь LatLngBounds и Bounds

LatLngBounds работает в географических координатах, а Bounds — в пикселях. Между ними существует преобразование через проекцию:

  • LatLng → Point через CRS
  • Point → LatLng через обратную проекцию

Это разделение позволяет Leaflet сохранять независимость логики карты и визуального слоя.


Типовые сценарии использования

Автоматическое масштабирование под данные

const bounds = L.latLngBounds(dataPoints);
map.fitBounds(bounds);

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

map.setMaxBounds(
  L.latLngBounds([55.7, 37.5], [55.8, 37.7])
);

Проверка попадания объектов в видимую область

if (map.getBounds().contains(marker.getLatLng())) {
  // объект видим
}

Оптимизация рендера

if (!tileBounds.intersects(mapBounds)) {
  return;
}

Поведение при изменении масштаба

При зуме LatLngBounds остаётся неизменным, но его пиксельное представление (Bounds) пересчитывается каждый раз. Это обеспечивает согласованность данных при любом масштабе карты.


Особенности работы с массивами координат

При передаче массива координат порядок не важен:

L.latLngBounds([
  [55.8, 37.7],
  [55.7, 37.5],
  [55.75, 37.65]
]);

Leaflet автоматически вычисляет минимальные и максимальные значения.


Пограничные случаи

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

Использование в сложных слоях

При работе с GeoJSON и векторными слоями:

const geoBounds = geoJsonLayer.getBounds();
map.fitBounds(geoBounds);

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