Переключение между стилями

В MapLibre GL JS внешний вид карты полностью определяется стилем. Стиль представляет собой JSON-документ, описывающий:

  • источники данных (sources);
  • слои отображения (layers);
  • порядок отрисовки объектов;
  • цвета, шрифты и иконки;
  • правила визуализации геометрии.

Один и тот же набор данных может отображаться совершенно по-разному в зависимости от выбранного стиля. Например, карта может выглядеть как классическая дорожная схема, тёмная карта для ночного интерфейса или спутниковая подложка с дополнительными векторными слоями.

Именно поэтому переключение между стилями является одной из ключевых возможностей MapLibre GL JS.


Загрузка стиля при создании карты

Стиль задаётся через параметр style при инициализации карты:

const map = new maplibregl.Map({
    container: 'map',
    style: 'https://demotiles.maplibre.org/style.json',
    center: [37.6176, 55.7558],
    zoom: 10
});

После загрузки карта получает все необходимые настройки из указанного JSON-файла.


Метод setStyle()

Для смены стиля используется метод setStyle().

Базовый пример:

map.setStyle('https://example.com/styles/dark/style.json');

После вызова метода MapLibre:

  1. загружает новый JSON-стиль;
  2. получает связанные источники данных;
  3. создаёт новый набор слоёв;
  4. перерисовывает карту.

Фактически происходит полная замена текущего оформления.


Простое переключение между двумя стилями

Наиболее распространённый сценарий — переключение между светлой и тёмной темой.

HTML:

<button id="light">Светлая тема</button>
<button id="dark">Тёмная тема</button>

<div id="map"></div>

Jav * aScript:

const map = new maplibregl.Map({
    container: 'map',
    style: 'styles/light.json',
    center: [37.6176, 55.7558],
    zoom: 10
});

document.getElementById('light').addEventListener('click', () => {
    map.setStyle('styles/light.json');
});

document.getElementById('dark').addEventListener('click', () => {
    map.setStyle('styles/dark.json');
});

При нажатии на кнопку карта мгновенно переключается на другой стиль.


Использование выпадающего списка

Когда количество стилей превышает два, удобнее применять элемент <select>.

HTML:

<select id="style-selector">
    <option value="styles/light.json">Light</option>
    <option value="styles/dark.json">Dark</option>
    <option value="styles/satellite.json">Satellite</option>
</select>

Jav * aScript:

const selector = document.getElementById('style-selector');

selector.addEventListener('change', (event) => {
    map.setStyle(event.target.value);
});

Такой подход позволяет легко расширять список доступных оформлений.


Сохранение положения карты при смене стиля

Метод setStyle() изменяет только визуальное оформление.

Положение карты сохраняется автоматически:

  • координаты центра;
  • масштаб;
  • наклон;
  • вращение.

Пример:

map.setStyle('styles/dark.json');

После выполнения карта останется в той же точке мира и на том же уровне масштабирования.


Событие style.load

После смены стиля требуется дождаться полной загрузки нового оформления.

Для этого используется событие style.load.

map.on('style.load', () => {
    console.log('Стиль загружен');
});

Или:

map.setStyle('styles/dark.json');

map.once('style.load', () => {
    console.log('Новый стиль готов');
});

Событие особенно важно при работе с пользовательскими слоями.


Потеря пользовательских источников и слоёв

Одна из самых важных особенностей MapLibre GL JS заключается в том, что при вызове setStyle() удаляются:

  • добавленные вручную источники;
  • пользовательские слои;
  • изображения и иконки, зарегистрированные через API.

Например:

map.addSource('cities', {
    type: 'geojson',
    data: 'cities.geojson'
});

map.addLayer({
    id: 'cities-layer',
    type: 'circle',
    source: 'cities'
});

После выполнения:

map.setStyle('styles/dark.json');

слой cities-layer исчезнет.

Причина заключается в том, что новый стиль полностью заменяет старый.


Восстановление пользовательских слоёв

Наиболее распространённое решение — повторное добавление слоёв после загрузки нового стиля.

function addCitiesLayer() {

    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.on('load', addCitiesLayer);

map.on('style.load', () => {
    addCitiesLayer();
});

После каждой смены стиля слой будет автоматически восстанавливаться.


Проверка существования источника

При повторном добавлении необходимо избегать дублирования.

if (!map.getSource('cities')) {
    map.addSource('cities', {
        type: 'geojson',
        data: 'cities.geojson'
    });
}

Проверка особенно полезна в сложных приложениях с большим количеством динамических компонентов.


Сохранение пользовательских данных

Часто данные загружаются один раз и используются независимо от стиля.

Удобный подход — хранить конфигурацию отдельно.

const citiesSource = {
    type: 'geojson',
    data: 'cities.geojson'
};

const citiesLayer = {
    id: 'cities-layer',
    type: 'circle',
    source: 'cities',
    paint: {
        'circle-color': '#0080ff'
    }
};

Затем повторно использовать объекты:

map.addSource('cities', citiesSource);
map.addLayer(citiesLayer);

Так уменьшается количество дублируемого кода.


Переключение между локальными стилями

Стиль необязательно должен загружаться по URL.

Можно использовать локальные JSON-файлы.

Структура проекта:

styles/
├── light.json
├── dark.json
└── satellite.json

Подключение:

map.setStyle('./styles/dark.json');

Такой вариант часто применяется во внутренних корпоративных системах.


Использование объекта стиля вместо URL

Метод setStyle() принимает не только строку, но и готовый объект.

const darkStyle = {
    version: 8,
    sources: {},
    layers: []
};

map.setStyle(darkStyle);

Это позволяет формировать стиль программно.


Динамическое изменение стиля перед загрузкой

Стиль можно модифицировать непосредственно в JavaScript.

const style = structuredClone(baseStyle);

style.layers.forEach(layer => {

    if (layer.type === 'background') {
        layer.paint['background-color'] = '#111111';
    }

});

Затем применить:

map.setStyle(style);

Так создаются темы оформления без хранения множества отдельных JSON-файлов.


Создание переключателя день/ночь

Распространённый интерфейс — переключение темы по кнопке.

let darkMode = false;

button.addEventListener('click', () => {

    darkMode = !darkMode;

    map.setStyle(
        darkMode
            ? 'styles/dark.json'
            : 'styles/light.json'
    );

});

Такой механизм часто используется в административных панелях и аналитических системах.


Автоматическое переключение по системной теме

Современные браузеры позволяют определять текущую тему операционной системы.

const mediaQuery =
    window.matchMedia('(prefers-color-scheme: dark)');

Применение:

function applyTheme() {

    if (mediaQuery.matches) {
        map.setStyle('styles/dark.json');
    } else {
        map.setStyle('styles/light.json');
    }

}

applyTheme();

mediaQuery.addEventListener('change', applyTheme);

В результате карта автоматически адаптируется под системные настройки пользователя.


Переключение между векторной и спутниковой картой

Часто требуется отображать разные типы подложек.

document.getElementById('satellite')
    .addEventListener('click', () => {

        map.setStyle(
            'styles/satellite.json'
        );

    });

Либо:

document.getElementById('streets')
    .addEventListener('click', () => {

        map.setStyle(
            'styles/streets.json'
        );

    });

Так реализуются привычные переключатели «Карта» и «Спутник».


Изменение отдельных параметров вместо полной смены стиля

Полная замена стиля является относительно дорогой операцией.

Если необходимо изменить только некоторые параметры, предпочтительно использовать методы изменения свойств слоя.

Например:

map.setPaintProperty(
    'water',
    'fill-color',
    '#000033'
);

Или:

map.setPaintProperty(
    'roads',
    'line-color',
    '#ffffff'
);

Такой подход обеспечивает более плавную работу интерфейса.


Отслеживание загрузки нового стиля

Для проверки состояния карты используется метод:

map.isStyleLoaded();

Пример:

if (map.isStyleLoaded()) {
    console.log('Стиль готов');
}

Метод полезен при сложных сценариях инициализации приложения.


Обработка ошибок при смене стиля

Если стиль недоступен или содержит ошибки, MapLibre генерирует событие ошибки.

map.on('error', (event) => {
    console.error(event.error);
});

Распространённые причины:

  • неверный URL;
  • ошибка JSON;
  • отсутствие тайлового сервера;
  • недоступность шрифтов;
  • проблемы с сетевым подключением.

Наличие централизованного обработчика значительно упрощает диагностику.


Архитектура управления стилями

В крупных приложениях обычно создаётся отдельный менеджер стилей.

Пример:

const styles = {
    light: 'styles/light.json',
    dark: 'styles/dark.json',
    satellite: 'styles/satellite.json'
};

function switchStyle(name) {

    if (!styles[name]) {
        return;
    }

    map.setStyle(styles[name]);

}

Использование:

switchStyle('dark');
switchStyle('satellite');

Такой подход упрощает поддержку проекта и позволяет централизованно управлять всеми вариантами оформления карты.


Рекомендации по организации переключения стилей

Хранение пользовательских слоёв отдельно от базового стиля позволяет быстро восстанавливать их после вызова setStyle().

Использование события style.load гарантирует, что новый стиль полностью готов к работе.

Минимизация количества полных переключений помогает избежать лишних сетевых запросов и повторной инициализации ресурсов.

Разделение базовых и тематических стилей упрощает поддержку светлых, тёмных и специализированных вариантов отображения.

Программное создание стилей снижает необходимость хранить большое количество почти одинаковых JSON-файлов.

Централизованный менеджер стилей делает код масштабируемым и удобным для сопровождения в крупных веб-картографических приложениях.