Архитектура расширения Leaflet построена вокруг принципа минимального ядра и модульного наращивания функциональности. Базовая библиотека содержит только средства отображения карты, работу с тайлами, векторами, событиями и базовыми контролами. Любая дополнительная функциональность реализуется через плагины, которые интегрируются в систему через расширение классов, прототипов и событийной модели.
Плагины в Leaflet не требуют отдельного «регистрационного слоя».
Подключение происходит через выполнение JavaScript-кода, который
расширяет существующие классы или добавляет новые сущности в глобальное
пространство L.
Типовой порядок подключения:
Пример базовой структуры подключения:
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css">
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.markercluster/dist/leaflet.markercluster.js"></script>
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet.markercluster/dist/MarkerCluster.Default.css">
Большинство плагинов используют глобальный объект L как
точку расширения. Внутренняя структура Leaflet допускает добавление:
L.Class.extend)L.control,
L.layerGroup)Пример добавления нового слоя:
L.CustomLayer = L.Layer.extend({
onAdd: function(map) {
this._map = map;
this._container = L.DomUtil.create('div', 'custom-layer');
map.getPanes().overlayPane.appendChild(this._container);
},
onRemove: function(map) {
L.DomUtil.remove(this._container);
}
});
Экосистема Leaflet содержит несколько категорий расширений, каждая из которых взаимодействует с ядром по собственному механизму.
Расширяют систему отображения данных:
Пример: кластеризация маркеров через
Leaflet.markercluster
const markers = L.markerClusterGroup();
markers.addLayer(L.marker([51.5, -0.09]));
markers.addLayer(L.marker([51.495, -0.083]));
map.addLayer(markers);
Добавляют элементы управления интерфейсом:
Контролы регистрируются через L.Control.extend:
L.Control.Custom = L.Control.extend({
onAdd: function(map) {
const btn = L.DomUtil.create('button', 'custom-btn');
btn.innerHTML = 'Action';
return btn;
}
});
L.control.custom = function(opts) {
return new L.Control.Custom(opts);
};
Предоставляют математические и географические операции:
Эти плагины часто работают поверх L.LatLng,
L.GeometryUtil или сторонних библиотек.
Подключают внешние API и форматы:
Пример подключения WMS:
L.tileLayer.wms("https://example.com/wms", {
layers: 'basic',
format: 'image/png',
transparent: true
}).addTo(map);
Наиболее простой способ интеграции — загрузка через CDN:
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
<script src="https://unpkg.com/leaflet.fullscreen/Control.FullScreen.js"></script>
Преимущество заключается в отсутствии сборки и настройки бандлера.
В современных приложениях используется модульная система:
npm install leaflet leaflet.markercluster
Импорт в коде:
import L from 'leaflet';
import 'leaflet.markercluster';
При таком подходе плагины обычно автоматически расширяют объект
L.
Плагины Leaflet не имеют централизованной системы зависимостей, поэтому возможны конфликты:
L.MapТипичный источник ошибок — плагины, рассчитанные на разные версии ядра.
Рекомендуемые практики:
peerDependenciesПоследовательность подключения критична, поскольку плагины часто модифицируют глобальные классы:
Нарушение порядка приводит к:
undefined is not a functionПлагины активно используют событийную модель Leaflet:
map.on('click', function(e) {
console.log(e.latlng);
});
Расширенные плагины добавляют собственные события:
clusterGroup.on('clusterclick', function(a) {
console.log('Cluster clicked');
});
Система событий обеспечивает слабую связанность компонентов и позволяет интегрировать плагины без изменения ядра.
Структура типового плагина включает:
L.ClassLПример базового шаблона:
L.SimplePlugin = L.Class.extend({
initialize: function(options) {
this.options = options;
},
attach: function(map) {
this._map = map;
}
});
L.simplePlugin = function(options) {
return new L.SimplePlugin(options);
};
Leaflet работает поверх DOM через слои panes. Плагины,
добавляющие визуальные элементы, должны учитывать:
overlayPane,
markerPane)stopPropagationКорректное удаление DOM-элементов:
onRemove: function(map) {
L.DomUtil.remove(this._container);
this._container = null;
}
Некорректная интеграция плагинов может существенно снизить производительность карты.
Основные факторы нагрузки:
Оптимизационные подходы:
requestAnimationFrameПри использовании bundler-систем (Vite, Webpack, Rollup) плагины могут требовать:
Пример:
import 'leaflet/dist/leaflet.css';
import 'leaflet.markercluster/dist/MarkerCluster.css';
Некоторые плагины модифицируют прототипы напрямую:
L.Map.include({
customMethod: function() {
return 'extended';
}
});
Такой подход обеспечивает глобальную доступность метода, но требует осторожности из-за риска конфликтов.
Часто применяются следующие подходы:
Современные плагины используют альтернативные рендеры:
Пример концептуального слоя:
L.CanvasLayer = L.Layer.extend({
onAdd: function(map) {
this._canvas = L.DomUtil.create('canvas');
map.getPanes().overlayPane.appendChild(this._canvas);
}
});
Каждый плагин должен учитывать жизненный цикл карты:
initialize)onAdd)onRemove)Нарушение жизненного цикла приводит к утечкам памяти и «зависшим» DOM-узлам.
Экосистема расширений развивается в сторону:
Плагины становятся самостоятельными мини-библиотеками, а не простыми расширениями скриптов.