В MapLibre GL JS значительная часть логики приложения строится вокруг событий. Карта загружает стиль, тайлы, спрайты, шрифты, источники данных и пользовательские слои асинхронно. По этой причине выполнение многих операций сразу после создания объекта карты может привести к ошибкам или непредсказуемому поведению.
События загрузки позволяют определить момент, когда определённый этап инициализации завершён и можно безопасно выполнять дальнейшие действия:
Базовое создание карты выглядит следующим образом:
const map = new maplibregl.Map({
container: 'map',
style: 'https://demotiles.maplibre.org/style.json',
center: [37.6176, 55.7558],
zoom: 10
});
После выполнения конструктора карта ещё не готова к работе. Большинство действий необходимо выполнять внутри обработчиков соответствующих событий.
Для регистрации обработчика используется метод on():
map.on('load', () => {
console.log('Карта загружена');
});
Общий синтаксис:
map.on('имя_события', (event) => {
// обработка события
});
Удаление обработчика выполняется через метод off():
function onLoad() {
console.log('Карта готова');
}
map.on('load', onLoad);
map.off('load', onLoad);
Для однократного выполнения применяется метод
once():
map.once('load', () => {
console.log('Событие выполнится только один раз');
});
Событие load считается одним из наиболее важных в
MapLibre GL JS. Оно возникает после полной загрузки начального стиля
карты и готовности карты к дальнейшей настройке.
map.on('load', () => {
console.log('Карта полностью инициализирована');
});
После получения этого события безопасно:
Пример добавления слоя после загрузки:
map.on('load', () => {
map.addSource('cities', {
type: 'geojson',
data: './cities.geojson'
});
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities',
paint: {
'circle-radius': 6,
'circle-color': '#ff0000'
}
});
});
Нередко возникает ошибка:
map.addLayer({
id: 'test',
type: 'circle'
});
Если код выполняется сразу после создания карты, может появиться исключение:
Style is not done loading
Причина заключается в том, что стиль ещё не загружен.
Неправильно:
const map = new maplibregl.Map({...});
map.addLayer({...});
Правильно:
const map = new maplibregl.Map({...});
map.on('load', () => {
map.addLayer({...});
});
Событие style.load вызывается после загрузки стиля
карты.
map.on('style.load', () => {
console.log('Стиль загружен');
});
Особенно полезно при динамической смене стилей.
Например:
map.setStyle('style-dark.json');
После замены стиля все пользовательские слои удаляются, поскольку загружается новый объект стиля.
Для повторного добавления данных используется:
map.on('style.load', () => {
map.addSource('roads', {
type: 'geojson',
data: './roads.geojson'
});
map.addLayer({
id: 'roads-layer',
type: 'line',
source: 'roads'
});
});
Срабатывает при первой полной инициализации карты.
map.on('load', () => {
console.log('Первый запуск');
});
Срабатывает каждый раз после загрузки стиля.
map.on('style.load', () => {
console.log('Стиль готов');
});
Если стиль меняется несколько раз:
map.setStyle('style1.json');
map.setStyle('style2.json');
map.setStyle('style3.json');
Событие load выполнится один раз, а
style.load — после каждой загрузки нового стиля.
Позволяет отслеживать загрузку источников данных.
map.on('sourcedata', (e) => {
console.log(e);
});
Событие возникает при:
Пример:
map.on('sourcedata', (e) => {
if (e.sourceId === 'cities') {
console.log('Источник cities обновлён');
}
});
Объект события содержит большое количество служебной информации.
Пример:
map.on('sourcedata', (e) => {
console.log(e.sourceId);
console.log(e.sourceDataType);
console.log(e.isSourceLoaded);
});
Часто используемые свойства:
| Свойство | Описание |
|---|---|
| sourceId | Идентификатор источника |
| source | Объект источника |
| isSourceLoaded | Полностью ли загружен источник |
| sourceDataType | Тип изменения данных |
Иногда требуется дождаться завершения загрузки конкретного источника.
map.on('sourcedata', (e) => {
if (
e.sourceId === 'cities' &&
e.isSourceLoaded
) {
console.log('GeoJSON полностью загружен');
}
});
Такой подход полезен при работе с большими наборами данных.
Событие более общего уровня.
map.on('data', (e) => {
console.log(e);
});
Оно возникает при любых изменениях данных карты:
Пример:
map.on('data', (e) => {
console.log('Тип данных:', e.dataType);
});
Позволяет определить источник события.
map.on('data', (e) => {
console.log(e.dataType);
});
Возможные значения:
style
source
Проверка:
map.on('data', (e) => {
if (e.dataType === 'style') {
console.log('Изменился стиль');
}
if (e.dataType === 'source') {
console.log('Изменились данные источника');
}
});
Возникает при обновлении данных стиля.
map.on('styledata', () => {
console.log('Стиль обновлён');
});
Событие может вызываться несколько раз в процессе работы карты.
Например:
map.setPaintProperty(
'roads',
'line-color',
'#00ff00'
);
После изменения параметров слоя событие может быть вызвано повторно.
Сообщает о начале загрузки данных источника.
map.on('sourcedataloading', (e) => {
console.log('Начало загрузки');
});
Практический пример:
map.on('sourcedataloading', () => {
showLoader();
});
Возникает при начале загрузки данных стиля.
map.on('styledataloading', () => {
console.log('Стиль начал загружаться');
});
Применяется для отображения индикаторов загрузки во время смены темы карты.
Это общий аналог событий загрузки данных.
map.on('dataloading', () => {
console.log('Идёт загрузка данных');
});
Срабатывает раньше события data.
Типичная последовательность:
dataloading
data
Одно из наиболее полезных событий для контроля полной готовности карты.
map.on('idle', () => {
console.log('Карта находится в состоянии покоя');
});
Событие возникает тогда, когда:
Фактически это состояние полной готовности интерфейса.
map.on('load', () => {
map.addSource('buildings', {
type: 'geojson',
data: './buildings.geojson'
});
map.addLayer({
id: 'buildings-layer',
type: 'fill',
source: 'buildings'
});
map.once('idle', () => {
console.log('Все данные отображены');
});
});
В данном случае сообщение появится только после завершения загрузки и визуализации данных.
Иногда вместо событий требуется выполнить проверку программно.
if (map.isStyleLoaded()) {
console.log('Стиль уже готов');
}
Метод возвращает логическое значение:
true
false
Для конкретного источника:
const source = map.getSource('cities');
Однако обычно контроль осуществляется через события:
map.on('sourcedata', (e) => {
if (
e.sourceId === 'cities' &&
e.isSourceLoaded
) {
console.log('Источник готов');
}
});
Распространённый сценарий — отображение спиннера.
HTML:
<div id="loader">
Загрузка...
</div>
Jav * aScript:
map.on('dataloading', () => {
loader.style.display = 'block';
});
map.on('idle', () => {
loader.style.display = 'none';
});
Логика выглядит следующим образом:
idle.Сложные приложения обычно используют сразу несколько обработчиков.
map.on('load', initMap);
map.on('style.load', restoreLayers);
map.on('sourcedata', monitorSources);
map.on('idle', updateUI);
Где:
function initMap() {
console.log('Инициализация');
}
function restoreLayers() {
console.log('Восстановление слоёв');
}
function monitorSources(event) {
console.log(event.sourceId);
}
function updateUI() {
console.log('Обновление интерфейса');
}
Такой подход позволяет разделять ответственность между различными этапами жизненного цикла карты.
При первом запуске карты часто наблюдается следующая цепочка:
styledataloading
styledata
load
sourcedataloading
sourcedata
data
idle
При смене стиля:
styledataloading
style.load
styledata
sourcedataloading
sourcedata
idle
Конкретный порядок может незначительно отличаться в зависимости от конфигурации карты, количества источников и сетевых условий, однако понимание общей последовательности позволяет правильно организовывать логику инициализации, загрузки данных и обновления пользовательского интерфейса.