Корректное отображение карты в MapLibre GL JS зависит не только от настроек самой библиотеки, но и от структуры HTML-документа, CSS-стилей, параметров камеры, источников данных и состояния WebGL. Большинство визуальных ошибок связано именно с этими компонентами.
Наиболее распространённая проблема — контейнер карты присутствует в DOM, но карта остаётся невидимой.
Пример создания карты:
const map = new maplibregl.Map({
container: 'map',
style: 'style.json',
center: [37.6176, 55.7558],
zoom: 10
});
HTML:
<div id="map"></div>
Если контейнер не имеет размеров, карта не сможет отрисоваться.
Неправильный вариант:
#map {
}
Правильный вариант:
#map {
width: 100%;
height: 500px;
}
Также часто встречается ситуация, когда высота родительского элемента равна нулю.
Например:
<div class="wrapper">
<div id="map"></div>
</div>
.wrapper {
height: 0;
}
В таком случае карта также останется невидимой.
Если контейнер имеет размеры, но отображается только белый фон, причины обычно связаны со стилем карты.
Проверка загрузки стиля:
map.on('load', () => {
console.log('Стиль загружен');
});
Проверка ошибок:
map.on('error', (e) => {
console.error(e.error);
});
Типичные причины:
Пример ошибочного пути:
style: './styles/map.json'
Если файл фактически находится в другом каталоге:
style: './assets/styles/map.json'
карта не сможет загрузить данные.
Иногда карта видна только в одном углу контейнера либо часть области остаётся пустой.
Причина чаще всего связана с изменением размеров контейнера после инициализации карты.
Например:
const map = new maplibregl.Map({
container: 'map',
style: style
});
document.getElementById('map').style.height = '600px';
MapLibre уже вычислил размеры контейнера и не знает об изменениях.
Необходимо вызвать:
map.resize();
Пример:
window.addEventListener('resize', () => {
map.resize();
});
Особенно часто проблема возникает при использовании вкладок, модальных окон и аккордеонов.
Пример:
<div id="modal" style="display:none;">
<div id="map"></div>
</div>
Если карта создаётся в момент, когда контейнер скрыт:
const map = new maplibregl.Map({
container: 'map',
style: style
});
MapLibre получает размеры контейнера как 0×0.
После открытия блока требуется выполнить:
map.resize();
Например:
openModal();
map.resize();
Серые области свидетельствуют о том, что тайлы не были загружены.
Возможные причины:
Пример источника:
{
type: 'raster',
tiles: [
'https://server.example.com/{z}/{x}/{y}.png'
],
tileSize: 256
}
Если сервер возвращает ошибку 404:
GET ... 404 Not Found
соответствующие тайлы не будут отображены.
Проверка выполняется через вкладку Network в инструментах разработчика браузера.
Иногда маркеры и объекты находятся не там, где ожидается.
Причина часто заключается в неправильном порядке координат.
MapLibre использует формат:
[долгота, широта]
Верный пример:
[37.6176, 55.7558]
Ошибочный пример:
[55.7558, 37.6176]
Такая ошибка может перенести объект на другой континент.
Создание маркера:
new maplibregl.Marker()
.setLngLat([37.6176, 55.7558])
.addTo(map);
Если маркер отсутствует, следует проверить:
Иногда маркер оказывается за пределами текущего вида карты.
Проверка:
map.flyTo({
center: [37.6176, 55.7558],
zoom: 14
});
Причина может скрываться в пользовательском HTML.
Пример:
const el = document.createElement('div');
el.style.width = '0px';
el.style.height = '0px';
new maplibregl.Marker(el)
.setLngLat([37.6176, 55.7558])
.addTo(map);
Элемент фактически существует, но имеет нулевой размер.
Корректный вариант:
el.style.width = '20px';
el.style.height = '20px';
Добавление слоя:
map.addLayer({
id: 'roads',
type: 'line',
source: 'roads'
});
Частая ошибка — слой добавляется раньше источника.
Неправильно:
map.addLayer({
id: 'roads',
source: 'roads',
type: 'line'
});
map.addSource('roads', source);
Правильно:
map.addSource('roads', source);
map.addLayer({
id: 'roads',
source: 'roads',
type: 'line'
});
Следует проверить наличие данных.
Проверка GeoJSON:
console.log(data.features.length);
Пустой набор данных:
{
"type": "FeatureCollection",
"features": []
}
не приведёт к появлению объектов на карте.
Также необходимо проверить фильтры слоя.
Например:
filter: ['==', 'type', 'road']
Если объектов с таким свойством нет, слой останется пустым.
Причина часто связана с параметрами масштабирования.
Пример:
{
id: 'buildings',
type: 'fill',
source: 'buildings',
minzoom: 15
}
Слой начнёт отображаться только после достижения масштаба 15.
При масштабе:
zoom: 10
объекты не будут видны.
Проверка:
const layer = map.getLayer('buildings');
console.log(layer.minzoom);
Для символов используется слой типа symbol.
Пример:
{
id: 'cities',
type: 'symbol',
source: 'cities',
layout: {
'text-field': ['get', 'name']
}
}
Если поле отсутствует:
{
"population": 500000
}
надпись не появится.
Следует убедиться в наличии нужного атрибута:
{
"name": "Москва"
}
Для использования иконки её необходимо предварительно зарегистрировать.
Пример:
map.loadImage('/marker.png', (error, image) => {
if (error) throw error;
map.addImage('marker', image);
});
После этого:
layout: {
'icon-image': 'marker'
}
Если изображение не зарегистрировано, иконка отображаться не будет.
Проверка:
console.log(
map.hasImage('marker')
);
Причины:
Плохая практика:
setInterval(() => {
map.removeLayer('points');
map.addLayer(layer);
}, 100);
Лучше обновлять данные источника:
source.setData(newData);
На устройствах Retina карта иногда выглядит нечёткой.
Причины:
Плохой вариант:
#map {
transform: scale(1.5);
}
Такое масштабирование приводит к визуальному размытию.
Предпочтительно изменять размеры контейнера напрямую:
#map {
width: 1200px;
height: 800px;
}
При использовании параметра pitch:
map.setPitch(60);
могут появляться:
Особенно это заметно при работе с большими полигонами и 3D-экструзией.
Пример слоя:
{
id: 'buildings',
type: 'fill-extrusion'
}
Для диагностики полезно временно убрать наклон:
map.setPitch(0);
Если проблема исчезает, причина связана именно с перспективной проекцией.
MapLibre полностью зависит от WebGL.
Проверка поддержки:
if (!maplibregl.supported()) {
console.error('WebGL недоступен');
}
Причины отказа:
Дополнительная диагностика:
map.on('error', console.error);
При нехватке видеопамяти браузер может потерять контекст рендеринга.
Симптомы:
Причины:
Рекомендуется уменьшать объём данных и избегать создания большого
количества экземпляров Map.
Источник:
map.addSource('data', {
type: 'geojson',
data: hugeGeoJSON
});
Файлы размером в десятки мегабайт могут приводить к:
Способы решения:
После обновления GeoJSON на сервере карта может показывать старую версию.
Причина часто связана с кэшированием.
Источник:
data: '/api/data.geojson'
Для принудительного обновления иногда добавляют параметр версии:
data: `/api/data.geojson?v=${Date.now()}`
или корректно настраивают HTTP-заголовки кэширования на сервере.
Наиболее полезные инструменты поиска ошибок:
Проверка загрузки карты:
map.on('load', () => {
console.log('Map loaded');
});
Отслеживание ошибок:
map.on('error', (e) => {
console.error(e);
});
Проверка состояния источников:
console.log(
map.getStyle().sources
);
Проверка слоёв:
console.log(
map.getStyle().layers
);
Проверка размеров контейнера:
console.log(
map.getContainer().clientWidth,
map.getContainer().clientHeight
);
Систематическая проверка размеров контейнера, загрузки стиля, состояния источников, корректности координат и работы WebGL позволяет выявить подавляющее большинство проблем с отображением в приложениях на базе MapLibre GL JS.