В Leaflet масштабирование строится вокруг дискретной системы уровней масштаба (zoom levels), где каждый уровень представляет собой удвоение или уменьшение детализации карты. При увеличении масштаба карта загружает более детализированные тайлы, а при уменьшении — более крупные участки местности.
Основная характеристика системы:
Ключевой объект, управляющий масштабированием:
const map = L.map('map', {
center: [55.751244, 37.618423],
zoom: 10
});
Параметр zoom задаёт начальный уровень детализации,
который напрямую влияет на размер и плотность отображаемых тайлов.
Карты в Leaflet состоят из квадратных тайлов фиксированного размера (обычно 256×256 пикселей). При изменении масштаба происходит перерасчёт:
Пример подключения слоя тайлов:
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
minZoom: 1,
tileSize: 256,
attribution: '© OpenStreetMap contributors'
}).addTo(map);
При изменении zoom Leaflet автоматически пересчитывает
{z}, {x}, {y} и подгружает новые
изображения.
zoomSnap: 1
Определяет шаг изменения масштаба. При значении 1 карта
переключается строго по целым уровням. При значении 0.5
доступны промежуточные уровни.
zoomDelta: 1
Определяет, насколько изменяется zoom при одном шаге колёсика мыши или кнопки управления.
wheelPxPerZoomLevel: 120
Регулирует чувствительность масштабирования колесом мыши.
Leaflet предоставляет набор методов для управления zoom:
map.setZoom(12);
map.zoomIn();
map.zoomOut();
map.setView([55.75, 37.61], 13);
Плавное масштабирование:
map.flyTo([55.75, 37.61], 14);
Метод flyTo одновременно изменяет центр и масштаб,
используя анимацию с интерполяцией.
Для контроля диапазона используются параметры:
const map = L.map('map', {
minZoom: 5,
maxZoom: 18
});
Эти ограничения важны для:
Система координат (CRS) определяет, как географические координаты преобразуются в пиксели. По умолчанию используется Web Mercator:
crs: L.CRS.EPSG3857
При каждом изменении zoom происходит пересчёт:
Это позволяет поддерживать визуальную непрерывность карты при масштабировании.
На устройствах с высокой плотностью пикселей Leaflet может автоматически загружать увеличенные тайлы:
L.tileLayer(url, {
detectRetina: true,
tileSize: 256
});
При detectRetina: true происходит:
Векторные слои масштабируются иначе, чем тайлы.
Примеры объектов:
Маркер:
L.marker([55.75, 37.61]).addTo(map);
Маркер остаётся фиксированного размера на экране, но его географическая позиция пересчитывается при каждом изменении zoom.
Для кастомного масштабирования:
const icon = L.icon({
iconUrl: 'marker.png',
iconSize: [32, 32]
});
При необходимости динамического изменения размера можно привязаться к zoom:
map.on('zoomend', () => {
const zoom = map.getZoom();
const size = zoom * 2;
marker.setIcon(L.icon({
iconUrl: 'marker.png',
iconSize: [size, size]
}));
});
SVG-слои масштабируются через трансформации DOM:
transform: scaleCanvas-рендеринг работает иначе:
Пример включения Canvas:
const map = L.map('map', {
preferCanvas: true
});
Canvas особенно эффективен при большом количестве объектов, где SVG начинает деградировать по производительности.
map.scrollWheelZoom.disable();
touchZoom: false
doubleClickZoom: false
UI-элементы Leaflet (контролы) также привязаны к системе масштабирования, но не изменяют размер автоматически.
Пример стандартного управления:
L.control.zoom({
position: 'topright'
}).addTo(map);
Контролы остаются фиксированными в экранных координатах и не зависят от zoom карты. Это создаёт разделение:
При необходимости адаптации UI под zoom требуется ручная синхронизация:
map.on('zoomend', () => {
const zoom = map.getZoom();
const control = document.querySelector('.leaflet-control-zoom');
control.style.transform = `scale(${1 + zoom * 0.02})`;
});
Метод fitBounds рассчитывает оптимальный zoom для
отображения области:
map.fitBounds([
[55.7, 37.5],
[55.8, 37.7]
]);
Алгоритм:
Дополнительные параметры:
map.fitBounds(bounds, {
padding: [20, 20],
maxZoom: 15
});
Leaflet использует CSS transform для плавного изменения масштаба:
Настройка анимации:
const map = L.map('map', {
zoomAnimation: true,
zoomAnimationThreshold: 4
});
Если изменение zoom превышает threshold, анимация отключается ради производительности.
При каждом изменении zoom выполняются операции:
Оптимизационные подходы:
Кластеризация:
const markers = L.markerClusterGroup();
markers.addLayer(L.marker([55.75, 37.61]));
map.addLayer(markers);
Zoom-события:
map.on('zoomstart', () => {});
map.on('zoomend', () => {});
map.on('zoomlevelschange', () => {});
Пример динамического изменения прозрачности слоёв:
map.on('zoomend', () => {
const zoom = map.getZoom();
const opacity = Math.min(1, zoom / 10);
geoLayer.setStyle({
opacity
});
});
При увеличении zoom меняется не геометрия, а визуальное представление. Реальные расстояния вычисляются независимо от масштаба:
Пример добавления линейки:
L.control.scale({
imperial: false
}).addTo(map);
На мобильных устройствах zoom управляется жестами pinch:
Настройки:
touchZoom: true,
bounceAtZoomLimits: true
Bounce создаёт эффект упругости при достижении min/max zoom.
Система масштабирования в Leaflet представляет собой многослойную архитектуру:
Эта модель обеспечивает синхронную работу картографических данных, визуальных слоёв и интерфейсных элементов при любых изменениях масштаба.