Плагины в MapLibre GL JS представляют собой способ расширения функциональности карты без модификации ядра рендеринга. Архитектура библиотеки построена вокруг композиции модулей: карта, источники данных, слои, стили и внешние расширения взаимодействуют через публичные API. Плагины интегрируются в этот слой как независимые JavaScript-модули, подключаемые в рантайме или на этапе сборки приложения.
Основой системы расширений выступает объект карты, который предоставляет набор методов для управления состоянием визуализации, источниками данных и пользовательскими элементами интерфейса. Плагины используют эти методы как точку входа в систему.
Типичная модель плагина включает:
Плагины не имеют единого стандарта в строгом смысле, однако большинство из них следуют соглашению: экспорт функции инициализации, принимающей экземпляр карты.
Наиболее распространённый способ установки плагинов — использование npm или yarn. В экосистеме MapLibre большинство расширений распространяются как отдельные пакеты.
Установка базового набора инструментов:
npm install maplibre-gl
Далее устанавливается конкретный плагин, например контрол масштаба или маршрутизации:
npm install @maplibre/maplibre-gl-geocoder
или альтернативные расширения:
npm install maplibre-gl-compare
npm install maplibre-gl-draw
После установки пакет попадает в node_modules и становится доступным для импорта:
import maplibregl from "maplibre-gl";
import MapboxGeocoder from "@maplibre/maplibre-gl-geocoder";
Ключевой момент: плагины обычно требуют, чтобы основной экземпляр библиотеки был передан явно, поскольку они не всегда статически привязаны к глобальному объекту.
Современные сборщики (Vite, Webpack, Rollup) позволяют подключать плагины как ES-модули. Это предпочтительный подход, так как он обеспечивает tree-shaking и контроль зависимостей.
Пример инициализации карты с плагином:
import maplibregl from "maplibre-gl";
import MaplibreGlDirections from "maplibre-gl-directions";
const map = new maplibregl.Map({
container: "map",
style: "https://demotiles.maplibre.org/style.json",
center: [30.5, 50.5],
zoom: 9
});
map.addControl(new MaplibreGlDirections({
accessToken: "YOUR_TOKEN"
}));
В данном примере плагин реализует контрол, добавляемый через метод
addControl. Это наиболее типичный механизм интеграции
расширений UI-уровня.
В проектах без сборки можно подключать плагины через CDN. В этом случае они обычно доступны как глобальные переменные.
Подключение основной библиотеки:
<link href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" rel="stylesheet">
<script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
Подключение плагина:
<script src="https://unpkg.com/maplibre-gl-draw/dist/maplibre-gl-draw.js"></script>
Использование:
const map = new maplibregl.Map({
container: "map",
style: "https://demotiles.maplibre.org/style.json"
});
const draw = new MaplibreGlDraw();
map.addControl(draw);
При таком способе важно учитывать порядок загрузки скриптов: плагин должен подключаться после основной библиотеки.
Контролы — самый распространённый тип плагинов. Они добавляют элементы управления на карту: поиск, масштабирование, маршруты, измерения.
Контрол реализуется через интерфейс с методами:
onAdd(map)onRemove()Пример структуры:
class CustomControl {
onAdd(map) {
this.map = map;
this.container = document.createElement("div");
this.container.className = "custom-control";
return this.container;
}
onRemove() {
this.container.parentNode.removeChild(this.container);
this.map = undefined;
}
}
Установка:
map.addControl(new CustomControl(), "top-right");
Позиционирование контролов важно для UX: доступны области
top-left, top-right, bottom-left,
bottom-right.
Расширения типа draw добавляют возможность
интерактивного создания геометрии.
import MaplibreGlDraw from "maplibre-gl-draw";
const draw = new MaplibreGlDraw({
displayControlsDefault: false,
controls: {
polygon: true,
line_string: true,
point: true,
trash: true
}
});
map.addControl(draw);
Такие плагины используют внутренние источники GeoJSON и динамически обновляют их через API карты.
Геокодеры подключаются как контролы, но требуют дополнительной настройки API.
import MaplibreGeocoder from "@maplibre/maplibre-gl-geocoder";
const geocoder = new MaplibreGeocoder({
forwardGeocode: async (config) => {
const response = await fetch(`/api/geocode?q=${config.query}`);
const data = await response.json();
return {
features: data.features
};
}
});
map.addControl(geocoder);
Здесь ключевая особенность — плагин не привязан к конкретному провайдеру, а требует реализации функции поиска.
В крупных приложениях плагины интегрируются как часть архитектуры приложения.
Пример структуры проекта:
src/
map/
index.js
plugins/
draw.js
geocoder.js
customControl.js
Файл инициализации карты:
import maplibregl from "maplibre-gl";
import { initDraw } from "./plugins/draw";
import { initGeocoder } from "./plugins/geocoder";
export function createMap() {
const map = new maplibregl.Map({
container: "map",
style: "/style.json"
});
initDraw(map);
initGeocoder(map);
return map;
}
Такой подход позволяет изолировать плагины от логики UI и бизнес-слоя.
Некоторые архитектуры используют централизованный менеджер плагинов.
Пример:
class PluginManager {
constructor(map) {
this.map = map;
this.plugins = [];
}
use(plugin) {
const instance = plugin(this.map);
this.plugins.push(instance);
return instance;
}
destroy() {
this.plugins.forEach(p => p.destroy?.());
}
}
Использование:
const manager = new PluginManager(map);
manager.use(initDrawPlugin);
manager.use(initGeocoderPlugin);
Это упрощает контроль за утечками памяти и порядком инициализации.
Плагины часто добавляют пользовательские слои рендеринга через API
addLayer.
map.on("load", () => {
map.addLayer({
id: "custom-layer",
type: "circle",
source: "points",
paint: {
"circle-radius": 6,
"circle-color": "#ff0000"
}
});
});
Расширенные плагины могут инкапсулировать создание источников:
export function initHeatmapPlugin(map) {
map.addSource("heat", {
type: "geojson",
data: "/data/heat.json"
});
map.addLayer({
id: "heat-layer",
type: "heatmap",
source: "heat"
});
}
Плагины тесно зависят от версии ядра MapLibre GL JS. Несовместимость API может проявляться в:
Map объектаРекомендуется фиксировать версии:
{
"dependencies": {
"maplibre-gl": ">=3.0.0 <4.0.0"
}
}
и проверять peerDependencies у каждого плагина.
Часто встречающиеся проблемы:
1. Двойная загрузка библиотеки Если MapLibre подключён через CDN и npm одновременно, возникает конфликт глобальных объектов.
2. Отсутствие CSS плагина Многие плагины требуют отдельного CSS:
import "maplibre-gl/dist/maplibre-gl.css";
import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css";
3. Несоответствие версий Плагин может использовать устаревшие методы API.
4. Неправильный порядок инициализации Контролы
добавляются до события load, что приводит к ошибкам:
map.on("load", () => {
map.addControl(plugin);
});
Плагины могут комбинироваться, формируя сложные системы:
map.addControl(draw);
map.addControl(geocoder);
map.addControl(scaleControl);
или через композицию:
function initPlugins(map) {
return [
initDraw(map),
initGeocoder(map),
initCustomLayers(map)
];
}
Такой подход позволяет строить модульные геоинформационные интерфейсы, где каждый плагин отвечает за строго ограниченную область поведения карты.
Плагины часто выступают мостом между картой и внешними API:
Пример маршрутизации:
map.addControl(new MaplibreGlDirections({
api: "https://router.project-osrm.org/route/v1"
}));
Такая архитектура отделяет визуализацию от логики вычислений.
Хорошо спроектированный плагин обычно включает:
Пример шаблона:
export function createPlugin(options = {}) {
let map;
return {
onAdd(m) {
map = m;
// init
},
onRemove() {
// cleanup
map = null;
}
};
}
Такая структура обеспечивает предсказуемость поведения и упрощает интеграцию в большие приложения.