Выражения для step

В стилях MapLibre GL JS выражение step используется для построения ступенчатых (piecewise constant) функций, где значение изменяется скачкообразно при достижении заданных порогов. Такой подход применяется для дискретной классификации данных: масштабирование символов, категоризация числовых атрибутов, настройка визуальных интервалов без интерполяции между ними.

Базовая структура step выражения имеет следующий вид:

["step", input, output0, stop1, output1, stop2, output2, ...]
  • input — входное значение (число или выражение)
  • output0 — значение по умолчанию (если input меньше первого порога)
  • stopN — пороговое значение
  • outputN — результат, применяемый если input ≥ stopN

Логика работы определяется последовательным сравнением:

  • если input < stop1 → используется output0
  • если stop1 ≤ input < stop2 → используется output1
  • если input ≥ lastStop → используется последний outputN

Механика вычисления

Выражение вычисляется слева направо, без интерполяции. Это ключевое отличие от interpolate. Значение не «плавно» меняется, а перескакивает между заранее заданными состояниями.

Для каждого входного значения выполняется поиск первого порога, который оно не превышает. После этого выбирается соответствующий выход.

Принцип можно представить как последовательность условий:

if input < stop1 → output0
else if input < stop2 → output1
else → output2

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

step часто применяется к свойствам геометрии или атрибутам из векторных тайлов. Значение извлекается через выражение ["get", "property"].

Пример изменения цвета объектов в зависимости от числового поля population:

[
  "step",
  ["get", "population"],
  "#fee5d9",
  1000,
  "#fcae91",
  5000,
  "#fb6a4a",
  20000,
  "#cb181d"
]

Здесь формируется классификация:

  • менее 1000 → светлый оттенок
  • 1000–4999 → слегка насыщенный
  • 5000–19999 → более тёмный
  • 20000 и выше → самый тёмный

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

Использование с масштабом карты

Одно из наиболее распространённых применений step — адаптация визуализации к уровню зума. Входным значением выступает ["zoom"].

Пример изменения радиуса точек:

[
  "step",
  ["zoom"],
  2,
  5,
  4,
  10,
  8,
  15,
  16
]

Интерпретация:

  • зум < 5 → радиус 2
  • 5–9 → радиус 4
  • 10–14 → радиус 8
  • 15 и выше → радиус 16

Такая схема позволяет контролировать визуальную плотность объектов на разных масштабах.

Дискретная классификация вместо интерполяции

Ключевая особенность step заключается в отсутствии плавных переходов. Значение остаётся постоянным внутри интервала.

Это делает выражение подходящим для задач, где:

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

Пример: изменение размера символов зданий в зависимости от типа плотности застройки.

[
  "step",
  ["get", "density"],
  1,
  3,
  2,
  6,
  3
]

Здесь каждый диапазон соответствует отдельному визуальному классу.

Работа с логическими границами

Пороги (stop значения) должны быть упорядочены по возрастанию. Нарушение порядка приводит к некорректной классификации или игнорированию части выражения.

Корректная структура:

stop1 < stop2 < stop3

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

Комбинация с другими выражениями

step часто комбинируется с другими конструкциями выражений.

С case логикой через вложенность

Хотя в MapLibre GL JS есть case, step может использоваться как более компактная альтернатива числовой классификации.

С interpolate для гибридных эффектов

В некоторых случаях применяется комбинированный подход:

  • step задаёт резкие переходы между диапазонами
  • внутри диапазона используется interpolate для плавной детализации

Пример: изменение прозрачности в зависимости от зума с порогами.

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

step применяется в большинстве визуальных свойств слоёв:

  • circle-radius
  • circle-color
  • line-width
  • fill-opacity
  • text-size

Пример для линий:

[
  "step",
  ["zoom"],
  0.5,
  8,
  1,
  12,
  2,
  16,
  4
]

Линии постепенно становятся визуально более выраженными при увеличении масштаба.

Типизация входных значений

Входное значение может быть:

  • числом (результат ["get", ...])
  • текущим масштабом (["zoom"])
  • результатом арифметического выражения (["+", ...], ["*", ...])
  • комбинированным вычислением

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

Поведение при отсутствии порогов

Если указано только:

["step", input, output0]

то выражение всегда возвращает output0, независимо от входного значения.

При добавлении одного порога:

["step", input, output0, 10, output1]

логика упрощается до бинарного выбора:

  • input < 10 → output0
  • input ≥ 10 → output1

Практические особенности производительности

Выражение step вычисляется на уровне рендеринга стиля и оптимизировано для WebGL-пайплайна MapLibre. Оно не требует дополнительных JavaScript-вычислений на стороне приложения, что снижает нагрузку при работе с большими наборами данных.

Особенно эффективно при:

  • отображении десятков тысяч объектов
  • динамическом изменении зума
  • сложных тематических слоях

Типичные сценарии применения

  • Классификация плотности населения
  • Разбиение скоростей дорог на категории
  • Упрощённая визуализация температурных диапазонов
  • Масштабируемые размеры точек на карте
  • Ступенчатое изменение прозрачности слоёв

Каждый из этих сценариев опирается на дискретную природу выражения, где важнее категория, чем точное значение.

Ограничения модели

step не предназначен для:

  • плавной визуализации градиентов
  • непрерывной анимации значений
  • сложных условных деревьев с множественными зависимостями

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

Семантика порогов

Пороговые значения интерпретируются включительно по правой границе:

  • левый интервал открыт
  • правый интервал закрыт

Это означает, что значение ровно равное stopN относится к следующему диапазону.

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