# Leaflet

## Що це таке

Leaflet — це бібліотека JavaScript із відкритим кодом, яка перетворює один
елемент вебсторінки на карту, яку можна панорамувати, масштабувати й натискати.
Проєкт оцінює її розмір приблизно в 42 KB JavaScript і зазначає, що вона
обходиться без зовнішніх залежностей. Її створив Володимир Агафонкін, тепер її
розвиває спільнота учасників, а поширюється вона за ліцензією BSD 2-Clause.

Власний огляд проєкту каже, що Leaflet не намагається робити все для всіх і
зосереджується на тому, щоб базові речі працювали добре. `L.map` приймає елемент
і набір параметрів і стає картою. Шар плиток завантажує квадратні зображення за
шаблоном URL із `{z}`, `{x}` і `{y}` і розкладає їх сіткою елементів зображень,
а варіант WMS робить те саме з Web Map Service. Ламані, полігони, кола й
прямокутники за замовчуванням малюються як SVG або на одному canvas, якщо карту
створено з `preferCanvas`. Маркери — це іконки, зображення або звичайний `div`,
до яких прив'язуються спливні вікна й підказки. Шар GeoJSON перетворює кожен
об'єкт на один із цих шарів, а точку — на маркер, якщо не вказано інше. Кнопки
масштабу, атрибуція, перемикач шарів і масштабна лінійка становлять елементи
керування. Система координат за замовчуванням — EPSG:3857, яку довідник називає
найпоширенішою для онлайн-карт.

Усе, що виходить за межі цього списку, дають плагіни. База плагінів проєкту
описує Leaflet як задуманий бути якомога легшим і вказує на сотні сторонніх
плагінів, розкладених за групами: векторні плитки, кластеризація, теплові карти,
редагування геометрії, маршрутизація, геокодування.

На момент написання існують дві лінії випусків. Стабільна — 1.9.4, випущена 18
травня 2023 року, і саме її відображає довідник API на сайті проєкту. Попередній
випуск 2.0.0-alpha.1 від 16 серпня 2025 року прибирає підтримку Internet
Explorer і постачається як ES-модуль. Глобальний `L` у ньому лишається тільки в
зібраному файлі `leaflet-global.js`, фабричні функції замінено конструкторами,
тож `L.marker(latlng)` стає `new Marker(latlng)`, а введення обробляється через
pointer events.

## Чому це важливо

Додати карту на сторінку — це два рішення, які легко сплутати з одним: який код
малює карту в браузері і звідки беруться зображення карти. Leaflet тримає їх
окремо, і вибір Leaflet здебільшого означає вибір тримати їх окремо.

Leaflet малює. Плитки надходять звідти, куди вказує шаблон URL, тож базова карта
— окреме рішення з власною ціною, умовами й власником. Це може бути сервер
плиток OpenStreetMap, поки функцію розробляють, комерційний постачальник у
продакшні, сервер плиток, який проєкт тримає сам, або WMS міської адміністрації
через `TileLayer.WMS`. Перехід між ними змінює один рядок у коді й текст
атрибуції, а код застосунку навколо карти лишається як є.

Розмір і ліцензія визначають, де Leaflet почувається природно. Близько 42 KB і
відсутність залежностей пасують сторінці, де карта — одна частина серед
багатьох: формі, де людина ставить шпильку, чи адмінпанелі, що показує, де
розташовані записи. Ліцензія BSD 2-Clause не ставить між бібліотекою і сторінкою
ні облікового запису, ні ключа, ні лічильника.

Ціна малого ядра в тому, що важчі функції приходять окремими пакетами, кожен зі
своїм супровідником і темпом випусків, і карта, що спирається на шість плагінів,
успадковує шість шляхів оновлення. Альфа 2.0 показує, що це означає: її нотатки
про перехід на нову версію радять користувачам старіших плагінів поліфіл V1, бо
ці плагіни очікують глобальний `L` і фабричні функції. Карті, якій потрібні
векторні плитки зі стилями в браузері на кожному рівні масштабу, краще підходить
бібліотека, побудована довкола них, і це рішення варто ухвалити раніше, ніж
шість плагінів триматимуть карту.

## Як це виглядає на практиці

Leaflet з'являється на двох сторінках цього сайту, обидві — з ролі керівника
команди розробки GIS-програмного забезпечення у 2015–2022 роках, і на обох він
ділить фронтенд із Mapbox.

Роль охоплювала постачання
[понад тридцяти GIS-проєктів від розробки й розгортання до підтримки](/uk/portfolio/led-the-development-deployment-and-support-of-over-35/).
На фронті цих проєктів стояли вебкарти на Mapbox GL і Leaflet, іноді з
використанням API ArcGIS чи HERE, а рівень застосунку писали на JavaScript,
Python, PHP і SQL. Під ними лежав PostgreSQL із PostGIS, а GDAL/OGR переносив
дані між shapefile, GeoJSON, GeoTIFF, KML і векторними плитками.
Відповідальність сягала далі за запуск, аж до підтримки в продакшні.

Та сама роль брала участь і в
[проєктуванні інтерфейсів цих проєктів](/uk/portfolio/contributed-to-user-interface-design-processes-ensuring-intuitive-36/).
Це були фронтенди на React, Angular і Vue поверх карт Mapbox і Leaflet, і
сторінка робить зауваження, яке варто тримати поруч із будь-якою картографічною
бібліотекою: у вебкартографічному продукті карта — найпростіша частина, а
губляться люди в елементах керування, фільтрації та потоці навколо неї.
Зручність залежала від деталей, як-от того, як фільтрувався набір даних і як
людина переходила між поверхами на карті приміщення, і більшу частину різниці
сторінка пояснює тим, що ці питання ставили під час дизайну, а не після релізу.

## Де виникають проблеми

Leaflet досить малий, щоб більшість його збоїв походила зі сторінки навколо
нього або від сервісів, на які він спрямований.

**Карта показується як сірий прямокутник або смужка розкиданих плиток.** Leaflet
бере розмір від свого контейнера. Посібник Quick Start називає дві речі, які
треба зробити до запуску будь-якого коду карти: підключити CSS-файл Leaflet
перед JavaScript і задати контейнеру визначену висоту. `div` без висоти дає
карту без висоти. Підступніший випадок — карта, створена у вкладці чи діалозі,
які в той момент приховані: вона вимірює себе як нуль і зберігає цей розмір,
коли з'являється. Leaflet 1.x стежить за зміною розміру вікна браузера через
`trackResize`, тож контейнер, що змінює розмір сам, лишається непоміченим, доки
код не викличе `invalidateSize()`, який довідник радить викликати після зміни
розміру карти. Альфа 2.0 використовує `ResizeObserver` замість події resize
вікна.

**Точки опиняються за тисячі кілометрів.** GeoJSON, як його визначає RFC 7946,
записує позицію з довготою першою. `LatLng` у Leaflet і масиви, які бібліотека
приймає замість нього, мають широту першою. `L.geoJSON` сам перетворює одне в
інше, тож помилка з'являється, коли координати витягають із GeoJSON вручну й
передають прямо в маркер чи ламану. Точка в Копенгагені з переставленими
координатами потрапляє в Аравійське море. Розпакуйте пару в іменовані змінні на
межі:

```js
const res = await fetch("/api/sites/42");
const site = await res.json();
const [lon, lat] = site.geometry.coordinates; // GeoJSON: lon, lat
L.marker([lat, lon]).addTo(map); // Leaflet: lat, lng
```

**Панорамування смикається, коли даних стає більше.** Із рендерером SVG кожна
лінія чи полігон — окремий елемент документа, і кожен стандартний маркер —
окреме зображення. Шар із багатьма тисячами об'єктів — це багато тисяч
елементів, які браузер має пересувати під час кожного панорамування й
масштабування. `preferCanvas: true` малює контури на одному canvas, але
стосується лише контурів, тож точки треба перетворити на `L.circleMarker`, коло
з фіксованим радіусом у пікселях, яке саме є контуром, через параметр
`pointToLayer` шару GeoJSON. Далі відповідь — надсилати менше: плагін
кластеризації або API, що повертає лише те, що вміщується в поточний вид і
масштаб.

**Плитки перестають завантажуватися після запуску.** Посібник Quick Start будує
першу карту на сервері плиток OpenStreetMap і прямо каже, що ці плитки годяться
для програмування, але перед продакшеном слід прочитати Tile Usage Policy. Ці
правила вимагають видимої атрибуції, User-Agent, що ідентифікує застосунок, і
коректного Referer із вебсторінок, кешування відповідно до HTTP-заголовків, а
масове й попереднє завантаження плиток забороняють. Вони не дають угоди про
рівень обслуговування й дозволяють заблокувати доступ без попередження.
Навантаженій продакшен-карті місце в постачальника, чиї умови пасують до її
трафіку, або на власному сервері плиток, і з Leaflet такий перехід зводиться до
шаблону URL і тексту атрибуції.

## Що почитати далі

- [Leaflet](https://leafletjs.com/) — огляд проєкту, перелік можливостей і перша
  карта в кілька рядків.
- [Leaflet API reference](https://leafletjs.com/reference.html) — кожен клас,
  параметр і метод у 1.9.4, зокрема `preferCanvas`, `invalidateSize` і параметри
  GeoJSON.
- [Leaflet Quick Start Guide](https://leafletjs.com/examples/quick-start/) —
  CSS, висота контейнера й перший шар плиток, крок за кроком.
- [Leaflet 2.0 Alpha released](https://leafletjs.com/2025/05/18/leaflet-2.0.0-alpha.html)
  — що змінюється у 2.0 і як мігрувати код і плагіни.
- [Tile Usage Policy](https://operations.osmfoundation.org/policies/tiles/) —
  умови користування серверами плиток openstreetmap.org.
- [RFC 7946: The GeoJSON Format](https://www.rfc-editor.org/rfc/rfc7946) —
  стандарт GeoJSON, зокрема порядок позицій із довготою першою.

<https://engineer.company/uk/glossary/leaflet/>
