Работа с базовыми стилями

Базовый стиль в MapLibre GL JS определяет визуальную структуру карты: какие слои отображаются, из каких источников поступают данные, как интерпретируются геометрии и каким образом применяются визуальные свойства. Вся система рендеринга в MapLibre опирается на единый JSON-документ стиля, который описывает источники данных, слои, фильтры, шрифты, спрайты и правила отображения.

Ключевая идея заключается в разделении данных и визуального представления. Источники (sources) предоставляют геометрию, а стили (layers) определяют, как эти данные должны быть отрисованы. Такая архитектура позволяет динамически переключать внешний вид карты без изменения самих данных.


Стиль в MapLibre GL JS представляет собой объект, соответствующий спецификации Mapbox Style Specification. Он включает несколько обязательных компонентов:

  • version — версия спецификации
  • sources — набор источников данных
  • layers — список визуальных слоёв
  • sprite — ссылка на спрайты иконок
  • glyphs — шаблон загрузки шрифтов
  • center, zoom, bearing, pitch — параметры начального положения камеры

Пример минимального стиля:

{
  "version": 8,
  "sources": {
    "osm": {
      "type": "vector",
      "url": "https://example.com/tiles.json"
    }
  },
  "layers": []
}

Даже в таком минимальном виде карта уже может быть создана, но без слоёв она не будет отображать визуальные данные.


Подключение стиля в MapLibre GL JS

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

import maplibregl from "maplibre-gl";

const map = new maplibregl.Map({
  container: "map",
  style: {
    version: 8,
    sources: {},
    layers: []
  },
  center: [37.6173, 55.7558],
  zoom: 10
});

Чаще используется загрузка стиля по URL:

const map = new maplibregl.Map({
  container: "map",
  style: "https://demotiles.maplibre.org/style.json",
  center: [0, 0],
  zoom: 2
});

URL-стиль позволяет централизованно управлять визуализацией карты, обновляя JSON без изменения клиентского кода.


Источники данных (sources)

Источники являются фундаментом любого стиля. Они определяют, откуда берутся географические данные.

Наиболее распространённые типы:

  • vector — векторные тайлы (геометрия + атрибуты)
  • raster — растровые тайлы (изображения)
  • geojson — локальные или удалённые GeoJSON-данные
  • image — одиночные изображения
  • video — видеослои (редко используются)

Пример векторного источника:

"sources": {
  "streets": {
    "type": "vector",
    "url": "https://tiles.server.com/streets.json"
  }
}

Пример GeoJSON источника:

"sources": {
  "points": {
    "type": "geojson",
    "data": {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "geometry": {
            "type": "Point",
            "coordinates": [30, 60]
          }
        }
      ]
    }
  }
}

GeoJSON часто используется для динамических данных, тогда как vector tiles оптимальны для больших наборов информации.


Слои (layers) и их роль

Слои определяют, как именно данные из sources отображаются на карте. Каждый слой связан с источником и типом визуализации.

Основные типы слоёв:

  • fill — заливка полигонов
  • line — линии (дороги, границы)
  • symbol — текст и иконки
  • circle — точки
  • heatmap — тепловые карты
  • fill-extrusion — 3D-экструзии

Пример слоя линий:

{
  "id": "roads",
  "type": "line",
  "source": "streets",
  "source-layer": "road",
  "paint": {
    "line-color": "#ff0000",
    "line-width": 2
  }
}

Каждый слой имеет:

  • id — уникальный идентификатор
  • type — тип визуализации
  • source — источник данных
  • source-layer — слой внутри векторного тайла (если применимо)
  • paint — визуальные свойства
  • layout — поведение слоя (видимость, порядок символов и т.д.)

Порядок слоёв и композиция

Слои в MapLibre отрисовываются в строгом порядке: от первого к последнему. Это означает, что порядок в массиве layers напрямую влияет на визуальную композицию.

Например:

"layers": [
  {
    "id": "background",
    "type": "background",
    "paint": {
      "background-color": "#e0e0e0"
    }
  },
  {
    "id": "water",
    "type": "fill",
    "source": "streets",
    "source-layer": "water",
    "paint": {
      "fill-color": "#a0c8f0"
    }
  }
]

Фон будет отрисован первым, затем водные объекты поверх него.


Базовые стили и их структура

Базовый стиль часто включает набор стандартных слоёв:

  • фон карты
  • водные объекты
  • леса и природные зоны
  • дороги разных классов
  • административные границы
  • подписи (labels)

Такая структура отражает классическую картографическую модель, где каждый уровень детализации отделён в отдельный слой.


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

MapLibre GL JS позволяет менять стиль на лету, что используется для переключения тем (светлая/тёмная), смены поставщика тайлов или визуальной переработки карты.

map.setStyle("https://demotiles.maplibre.org/style-dark.json");

При смене стиля происходит полная перезагрузка графа рендеринга, включая источники и слои.

Важно учитывать:

  • все добавленные вручную источники и слои удаляются
  • необходимо повторно добавлять кастомные элементы после загрузки нового стиля

Для восстановления используется событие:

map.on("styledata", () => {
  map.addSource("custom", {
    type: "geojson",
    data: "/data.geojson"
  });

  map.addLayer({
    id: "custom-layer",
    type: "circle",
    source: "custom",
    paint: {
      "circle-radius": 6,
      "circle-color": "#ff0000"
    }
  });
});

Работа с базовыми цветами и темами

Цветовая схема базового стиля определяет восприятие карты. Обычно выделяются две основные категории:

  • светлые стили (light theme)
  • тёмные стили (dark theme)

Смена темы затрагивает:

  • фон
  • контрастность дорог и воды
  • насыщенность подписей
  • прозрачность слоёв

Пример определения фона:

{
  "id": "background",
  "type": "background",
  "paint": {
    "background-color": "#ffffff"
  }
}

И для тёмной темы:

{
  "id": "background",
  "type": "background",
  "paint": {
    "background-color": "#0b0f14"
  }
}

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

MapLibre поддерживает expression-синтаксис, позволяющий динамически изменять стили в зависимости от масштаба, атрибутов и условий.

Пример изменения ширины линии в зависимости от zoom:

"line-width": [
  "interpolate",
  ["linear"],
  ["zoom"],
  5, 1,
  10, 3,
  15, 8
]

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


Масштабно-зависимое отображение

Базовые стили часто используют фильтрацию по zoom level:

"minzoom": 5,
"maxzoom": 12

Это позволяет скрывать или показывать слои в зависимости от масштаба карты. Например:

  • страны видны на малых масштабах
  • улицы — на средних
  • здания — на крупных

Работа с кастомными стилями

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

Типичная архитектура включает:

  • подключение векторных тайлов
  • определение базовых слоёв
  • настройку типографики через glyphs
  • использование спрайтов для иконок

Пример подключения шрифтов:

"glyphs": "https://fonts.server.com/{fontstack}/{range}.pbf"

Пример спрайтов:

"sprite": "https://assets.server.com/sprites/sprite"

Управление стилем через API

MapLibre предоставляет методы для манипуляции стилем после загрузки карты:

map.getStyle();
map.addSource();
map.removeSource();
map.addLayer();
map.moveLayer();
map.setLayoutProperty();
map.setPaintProperty();

Изменение цвета слоя:

map.setPaintProperty("roads", "line-color", "#00ff00");

Изменение видимости:

map.setLayoutProperty("roads", "visibility", "none");

Иерархия базового стиля

Внутри MapLibre стиль можно рассматривать как иерархическую систему:

  1. Источники данных (sources)
  2. Логическая структура слоёв (layers)
  3. Визуальные свойства (paint)
  4. Поведенческие свойства (layout)
  5. Камера (center, zoom, pitch)

Эта структура определяет весь цикл рендеринга карты — от данных до пикселей на экране.


Роль базового стиля в производительности

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

  • уменьшение числа активных слоёв снижает нагрузку на GPU
  • использование minzoom/maxzoom ограничивает отрисовку
  • оптимизация source-layer уменьшает объём обрабатываемых данных
  • грамотное использование expressions снижает необходимость JS-логики

Особенно критично количество symbol-слоёв, так как текстовые подписи требуют значительных ресурсов рендеринга.


Совместимость со стилями Mapbox

MapLibre GL JS использует открытую спецификацию, совместимую с Mapbox Style Specification. Это позволяет:

  • использовать существующие стили Mapbox
  • мигрировать стили без изменений структуры
  • применять готовые генераторы стилей

Однако некоторые проприетарные расширения Mapbox могут быть недоступны, поэтому базовые стили должны опираться на стандартные возможности спецификации.