Литералы и переменные

В спецификации стилей Mapbox GL JS значения свойств описываются через строго типизированные конструкции, где ключевое различие проходит между статическими литералами и динамическими выражениями. Это разделение определяет поведение слоя на этапе рендеринга и влияет на производительность, гибкость и возможность адаптации карты к данным и масштабу.

Литерал представляет собой неизменяемое значение, которое интерпретируется движком рендеринга напрямую, без вычислений и контекстной логики. В Mapbox GL JS литералы используются как базовая форма описания свойств стиля.

К числу литералов относятся:

  • строки: "#ff0000", "road", "Arial"
  • числа: 12, 0.5, 3
  • логические значения: true, false
  • массивы фиксированных значений: [1, 2, 3]

Пример использования литералов в стиле слоя:

map.addLayer({
  id: "roads",
  type: "line",
  source: "vector-source",
  "source-layer": "transportation",
  paint: {
    "line-color": "#ff6600",
    "line-width": 2
  }
});

В этом случае свойства line-color и line-width являются статическими. Они не зависят ни от данных, ни от масштаба. Результат вычисляется один раз на этапе применения стиля.

Литералы применяются там, где отсутствует необходимость в изменяемом поведении: фоновые цвета, базовая типографика, фиксированные отступы, декоративные элементы.

Литералы внутри выражений

В выражениях Mapbox GL JS существует отдельная форма явного литерала, оформляемая через оператор "literal". Он используется для предотвращения интерпретации массива как выражения.

Структура:

["literal", value]

Пример:

"circle-color": ["literal", "#00ff00"]

Без "literal" массив может быть интерпретирован как выражение, что изменит семантику. Это особенно критично при работе с вложенными структурами.

Использование "literal" гарантирует, что значение останется неизменным независимо от контекста вычисления.

Переменные в контексте Mapbox GL JS

В классическом смысле переменные отсутствуют, однако функционально их роль выполняют динамические источники данных, параметры состояния и системные атрибуты карты. Эти элементы выступают в роли контекстных переменных, влияющих на вычисление выражений.

Основные категории:

  • параметры масштаба (zoom)
  • свойства геометрии (feature properties)
  • состояние объекта (feature-state)
  • параметры времени и интерполяции

Каждая категория интегрируется в выражения через специальный синтаксис.


Масштаб как глобальная переменная

Уровень масштаба карты является одной из ключевых динамических величин. Он доступен через выражение "zoom" и используется для адаптивной стилизации.

Пример:

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

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

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


Свойства объектов как переменные данных

Каждый объект в источнике данных Mapbox GL JS содержит набор свойств (properties), которые могут использоваться в выражениях как динамические переменные.

Доступ осуществляется через:

["get", "property_name"]

Пример:

"circle-color": ["get", "color"]

В этом случае значение цвета берётся непосредственно из GeoJSON или векторного источника.

Допустим, объект имеет структуру:

{
  "type": "Feature",
  "properties": {
    "color": "#3366ff",
    "priority": 3
  }
}

Тогда стиль будет индивидуальным для каждого объекта.

Свойства могут участвовать в более сложных выражениях:

"circle-radius": [
  "interpolate",
  ["linear"],
  ["get", "priority"],
  1, 4,
  5, 20
]

Здесь priority выступает как переменная, влияющая на визуальное масштабирование.


Feature-state как изменяемая переменная состояния

Механизм feature-state представляет собой динамическое хранилище состояния, которое может изменяться без пересоздания источника данных.

Доступ:

["feature-state", "state_key"]

Пример:

"circle-opacity": [
  "case",
  ["boolean", ["feature-state", "hover"], false],
  1,
  0.5
]

Здесь состояние hover функционирует как переменная, управляющая прозрачностью.

Установка состояния выполняется программно:

map.setFeatureState(
  {
    source: "points",
    id: 42
  },
  {
    hover: true
  }
);

Такая модель позволяет реализовывать интерактивность без пересоздания слоя и без изменения GeoJSON.


Условные выражения как механизм управления переменными

Переменные в Mapbox GL JS часто используются через условные конструкции:

  • ["case", ...]
  • ["match", ...]

Пример case:

"line-color": [
  "case",
  ["==", ["get", "type"], "highway"],
  "#ff0000",
  "#999999"
]

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

Пример match:

"circle-color": [
  "match",
  ["get", "category"],
  "park", "#00ff00",
  "water", "#0000ff",
  "#cccccc"
]

Такие конструкции заменяют традиционные if-else и switch.


Комбинирование литералов и переменных

В реальных стилях литералы и переменные используются совместно, образуя вычислительные цепочки.

Пример:

"line-opacity": [
  "interpolate",
  ["linear"],
  ["zoom"],
  0, 0.2,
  10, ["get", "baseOpacity"],
  15, 1
]

Здесь:

  • 0.2 и 1 являются литералами
  • baseOpacity является переменной
  • zoom является системной переменной

Такое сочетание позволяет формировать гибридные модели визуализации.


Типизация значений и ограничения

Mapbox GL JS строго типизирует значения в выражениях. Литералы должны соответствовать ожидаемому типу свойства слоя:

  • цветовые значения — строки в формате CSS или RGB
  • размеры — числа
  • смещения — числа или массивы
  • фильтры — логические выражения

Несоответствие типов приводит к игнорированию свойства или ошибке компиляции стиля.

Пример некорректного использования:

"line-width": "large"

Корректный вариант:

"line-width": 5

или

"line-width": ["get", "width"]

Вложенные выражения как система вычислений

Переменные могут участвовать во вложенных выражениях, формируя многоуровневую логику.

Пример:

"circle-radius": [
  "interpolate",
  ["linear"],
  ["zoom"],
  5,
  ["*", ["get", "importance"], 2],
  10,
  ["*", ["get", "importance"], 5]
]

Здесь значение радиуса зависит одновременно от масштаба и атрибута объекта.

Такие конструкции превращают стиль в декларативную вычислительную модель.


Разграничение статического и динамического контекста

Литералы принадлежат статическому контексту стиля. Они вычисляются один раз при загрузке слоя.

Переменные принадлежат динамическому контексту. Их значения могут изменяться:

  • при изменении масштаба
  • при обновлении данных источника
  • при изменении feature-state
  • при перерендеринге сцены

Это разделение формирует основу архитектуры рендеринга Mapbox GL JS.


Оптимизация использования переменных

Чрезмерное использование динамических выражений увеличивает нагрузку на GPU и CPU. Литералы остаются наиболее дешёвым с точки зрения вычислений вариантом.

Оптимизационный принцип:

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

Пример неэффективного подхода:

"line-color": ["get", "staticColor"]

если значение никогда не меняется.

В таком случае предпочтительнее:

"line-color": "#3366ff"

Роль литералов и переменных в архитектуре стилей

Система стилей Mapbox GL JS фактически представляет собой декларативный язык, где литералы задают константную основу, а переменные формируют адаптивное поведение.

Взаимодействие этих элементов формирует три уровня:

  • базовый слой значений (литералы)
  • слой данных (feature properties)
  • слой вычислений (expressions)

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