Инициализация карты

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

Карта создаётся внутри элемента, например:

<div id="map"></div>

Критическим требованием является наличие высоты через CSS:

#map {
  height: 500px;
  width: 100%;
}

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

Базовая инициализация карты

Основной объект библиотеки — L.map. Он создаёт экземпляр карты и связывает его с DOM-элементом:

const map = L.map('map');

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

Чаще используется сразу установка центра и масштаба:

const map = L.map('map').setView([51.505, -0.09], 13);

Параметр setView принимает:

  • координаты центра [lat, lng]
  • уровень масштабирования (zoom)

Механика Leaflet строится на Web Mercator (EPSG:3857), поэтому координаты интерпретируются в географической системе широты и долготы, а затем проецируются в пиксельное пространство тайлов.

Добавление тайлового слоя

Карты Leaflet не содержат визуальных данных без слоя тайлов. Базовый слой подключается через L.tileLayer:

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);

URL содержит шаблонные параметры:

  • {s} — поддомен (a, b, c) для балансировки нагрузки
  • {z} — уровень масштаба
  • {x}, {y} — координаты тайла

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

  • maxZoom — максимальный доступный масштаб
  • minZoom — минимальный масштаб
  • attribution — строка атрибуции источника данных
  • tileSize — размер тайла (по умолчанию 256)
  • opacity — прозрачность слоя

Полный пример инициализации

const map = L.map('map', {
  center: [55.751244, 37.618423],
  zoom: 10,
  zoomControl: true,
  attributionControl: true
});

L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
  maxZoom: 19,
  attribution: '&copy; OpenStreetMap contributors'
}).addTo(map);

В отличие от setView, параметры center и zoom передаются напрямую в конфигурацию конструктора.

Параметры конструктора L.map

Объект инициализации карты поддерживает широкий набор опций, влияющих на поведение интерфейса и взаимодействия:

Управление интерфейсом

  • zoomControl — отображение кнопок масштабирования
  • attributionControl — отображение блока атрибуции
  • closePopupOnClick — закрытие всплывающих окон при клике по карте
  • boxZoom — масштабирование прямоугольником
  • doubleClickZoom — масштабирование двойным кликом
  • dragging — перетаскивание карты
const map = L.map('map', {
  zoomControl: false,
  doubleClickZoom: false,
  dragging: true
});

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

  • maxBounds — ограничение перемещения карты в пределах координат
  • minZoom и maxZoom — диапазон масштабов
const bounds = [
  [40.0, -74.0],
  [41.0, -73.0]
];

const map = L.map('map', {
  maxBounds: bounds,
  minZoom: 10,
  maxZoom: 16
});

maxBounds особенно важен при создании карт регионов, где выход за пределы логически нежелателен.

CRS и система координат

По умолчанию используется EPSG3857:

const map = L.map('map', {
  crs: L.CRS.EPSG3857
});

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

  • L.CRS.EPSG4326 (географическая система)
  • пользовательских CRS через L.Proj

Изменение CRS полностью влияет на расчёт тайлов и геометрию слоёв.

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

После создания объекта доступно множество методов управления:

Установка центра и масштаба

map.setView([48.8566, 2.3522], 12);

Также возможно раздельное управление:

map.setZoom(14);
map.setCenter([48.8566, 2.3522]);

В Leaflet фактически используется setView, а отдельные методы являются обёртками.

Плавная анимация перехода

map.flyTo([48.8566, 2.3522], 12);

или

map.panTo([48.8566, 2.3522]);

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

Перерисовка и корректировка размеров

Leaflet вычисляет размеры карты один раз при инициализации. При изменении DOM (например, открытии модального окна или изменении layout) требуется пересчёт:

map.invalidateSize();

Без этого метода возможны артефакты отображения тайлов и смещение центра.

Расширенный вариант с анимацией:

map.invalidateSize(true);

События и момент полной инициализации

Карта генерирует события жизненного цикла:

map.on('load', () => {
  // карта загружена
});

Другие важные события:

  • zoomend — завершение изменения масштаба
  • moveend — завершение перемещения
  • resize — изменение размеров контейнера
  • layeradd — добавление слоя
map.on('moveend', () => {
  const center = map.getCenter();
});

Удаление карты и освобождение ресурсов

При динамическом создании интерфейсов карта может быть уничтожена:

map.remove();

Удаление освобождает обработчики событий и очищает DOM-структуру, созданную Leaflet внутри контейнера.

Несколько карт на одной странице

Leaflet поддерживает множественные экземпляры:

const map1 = L.map('map1').setView([51.5, -0.09], 13);
const map2 = L.map('map2').setView([48.8, 2.35], 12);

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

Типичные ошибки и особенности поведения

Отсутствие размера контейнера

Без CSS-высоты карта не отображается, хотя объект успешно создаётся.

Инициализация скрытого контейнера

Если карта создаётся внутри скрытого элемента (display: none), размеры вычисляются некорректно, что требует вызова invalidateSize после отображения.

Несоответствие координат центра

Leaflet ожидает порядок [lat, lng]. Обратный порядок приводит к смещению карты в неправильную точку.

Повторная инициализация на одном контейнере

Создание второй карты на том же DOM-элементе без удаления первой приводит к конфликту состояния:

map.remove();
const map = L.map('map');

Опции производительности при инициализации

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

  • preferCanvas: true — использование Canvas вместо SVG для векторных слоёв
  • updateWhenIdle: true — обновление тайлов после завершения движения
  • keepBuffer — увеличение буфера тайлов вокруг видимой области
const map = L.map('map', {
  preferCanvas: true,
  updateWhenIdle: true
});

Canvas-рендеринг особенно эффективен при большом количестве геометрических объектов.

Контроль ограничений масштабирования и области

Комбинация ограничений часто используется для фиксации области интереса:

const map = L.map('map', {
  minZoom: 11,
  maxZoom: 16,
  maxBounds: [
    [55.0, 37.0],
    [56.0, 38.0]
  ]
});

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

Управление слоями при инициализации

Хотя слои обычно добавляются после создания карты, возможно их предварительное подключение:

const osm = L.tileLayer(url, options);

const map = L.map('map', {
  layers: [osm]
});

Это позволяет сразу задать базовую карту без дополнительного вызова .addTo(map).

Контроль масштабирования при старте

Leaflet позволяет задавать фиксированную точку обзора:

const map = L.map('map', {
  center: [59.93, 30.33],
  zoom: 10,
  zoomSnap: 1,
  zoomDelta: 1
});
  • zoomSnap — шаг округления масштаба
  • zoomDelta — шаг изменения при кнопках управления

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

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

При приближении до максимального уровня масштабирования Leaflet останавливает загрузку новых тайлов и фиксирует текущее состояние. При этом возможно отображение пустых областей, если сервер не предоставляет данные для максимального zoom.