Leaflet предоставляет механизм автоматической подгонки карты под
заданные географические границы. Основной инструмент для этого — метод
fitBounds, позволяющий масштабировать и центрировать карту
так, чтобы все точки или геометрия оказались в пределах видимой
области.
Метод работает с объектом LatLngBounds, который
описывает прямоугольную область на карте через две точки: юго-западную и
северо-восточную границы.
Границы создаются на основе набора координат или вручную:
const bounds = L.latLngBounds([
[55.75, 37.61],
[55.80, 37.70]
]);
Также границы могут быть вычислены из набора маркеров:
const marker1 = L.marker([55.75, 37.61]);
const marker2 = L.marker([55.80, 37.70]);
const bounds = L.latLngBounds([
marker1.getLatLng(),
marker2.getLatLng()
]);
В практических задачах чаще используется автоматическое построение границ из слоёв:
const group = L.featureGroup([marker1, marker2, marker3]);
const bounds = group.getBounds();
Метод применяется к экземпляру карты:
map.fitBounds(bounds);
Результатом является автоматическое вычисление:
В отличие от setView, где задаются фиксированные
координаты и zoom, fitBounds рассчитывает параметры
динамически.
Метод поддерживает дополнительную настройку поведения:
map.fitBounds(bounds, {
padding: [20, 20],
maxZoom: 15,
animate: true
});
Добавляет отступы от границ карты:
padding: [topBottom, leftRight]
или более детально:
paddingTopLeft: [20, 20],
paddingBottomRight: [20, 20]
Используется для предотвращения «прилипания» объектов к краям экрана.
Ограничивает максимальный уровень приближения:
maxZoom: 12
Применяется, когда область слишком мала, и автоматический zoom может оказаться чрезмерным.
Управляет анимацией перехода:
animate: true
При включении происходит плавное перемещение и масштабирование карты. Без анимации переход выполняется мгновенно.
Для анимации могут использоваться дополнительные параметры:
map.fitBounds(bounds, {
animate: true,
duration: 0.5,
easeLinearity: 0.25
});
duration — длительность анимацииeaseLinearity — характер ускорения/замедленияПри работе с GeoJSON границы вычисляются напрямую из слоя:
const geoJsonLayer = L.geoJSON(data);
map.fitBounds(geoJsonLayer.getBounds());
Метод getBounds() агрегирует все координаты объектов,
включая:
При группировке объектов используется FeatureGroup:
const group = L.featureGroup([marker1, marker2, polygon]);
map.fitBounds(group.getBounds());
Такой подход применяется для:
Если границы содержат только одну координату, Leaflet не может вычислить прямоугольник стандартным способом. В этом случае:
maxZoom;const bounds = L.latLngBounds([[55.75, 37.61]]);
map.fitBounds(bounds);
map.setView([55.75, 37.61], 10);
map.fitBounds(bounds);
fitBounds применяется при неизвестном заранее масштабе данных.
Дополнительно учитываются глобальные настройки карты:
const map = L.map('map', {
minZoom: 5,
maxZoom: 18
});
При вызове fitBounds итоговый zoom всегда приводится к
этим ограничениям.
При вызове fitBounds выполняется:
При частом обновлении данных используется предотвращение лишних перерисовок:
map.fitBounds(bounds, {
animate: false,
reset: true
});
Для больших наборов объектов предпочтительно:
requestAnimationFrame при потоковых
обновлениях.Если bounds не содержат координат, поведение неопределено:
Проверка:
if (bounds.isValid()) {
map.fitBounds(bounds);
}
При использовании maxBounds:
const map = L.map('map', {
maxBounds: L.latLngBounds([[50, 30], [60, 40]])
});
fitBounds не выходит за пределы этой области, даже если
данные требуют большего охвата.
При комбинировании нескольких источников данных:
const group = L.featureGroup();
geoJsonLayer.addTo(group);
markerLayer.addTo(group);
map.fitBounds(group.getBounds());
Общий bounds автоматически агрегирует все вложенные элементы.
После resize контейнера может потребоваться повторный вызов:
map.invalidateSize();
map.fitBounds(bounds);
invalidateSize обновляет внутренние вычисления размеров,
без чего fitBounds может дать некорректный результат.
При обновлении данных (например, фильтрация):
layer.clearLayers();
layer.addData(filteredData);
map.fitBounds(layer.getBounds());
При потоковой загрузке:
data.forEach(point => layer.addLayer(L.marker(point)));
map.fitBounds(layer.getBounds());
isValid();maxBounds.