Фильтры слоев

В Mapbox GL JS фильтры слоев определяют, какие объекты из источника данных будут отображаться в конкретном слое. Фильтрация выполняется на уровне client-side рендеринга и позволяет динамически управлять видимостью объектов без изменения исходного GeoJSON или векторных тайлов.

Фильтр слоя задаётся в свойстве filter объекта слоя и представляет собой выражение, построенное по принципам Mapbox Expression Syntax.


Базовая структура фильтра

Фильтр всегда является массивом, где первый элемент — оператор, а последующие элементы — операнды:

"filter": ["==", ["get", "type"], "restaurant"]

В этом примере отображаются только объекты, у которых свойство type равно "restaurant".

Фильтры применяются ко всем типам слоёв, работающим с векторными данными: fill, line, circle, symbol, fill-extrusion и другим.


Операторы сравнения

Равенство и неравенство

["==", ["get", "class"], "park"]
["!=", ["get", "class"], "industrial"]

Оператор == возвращает true, если значения совпадают. Оператор != — если значения различаются.


Сравнение чисел

[">", ["get", "population"], 100000]
[">=", ["get", "rank"], 5]
["<", ["get", "area"], 500]
["<=", ["get", "score"], 80]

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


Логические операторы

all

["all",
  ["==", ["get", "type"], "school"],
  [">", ["get", "students"], 500]
]

Все условия должны быть истинны.


any

["any",
  ["==", ["get", "type"], "hospital"],
  ["==", ["get", "emergency"], true]
]

Достаточно одного истинного условия.


none

["none",
  ["==", ["get", "type"], "construction"],
  ["==", ["get", "status"], "closed"]
]

Истина, если ни одно из условий не выполняется.


Проверка наличия свойств

has

["has", "name"]

Фильтрует объекты, у которых существует указанное свойство.

!has

["!has", "height"]

Используется для поиска объектов без определённого атрибута.


Работа с массивами значений

in

["in", ["get", "type"], "restaurant", "cafe", "bar"]

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

!in

["!in", ["get", "type"], "road", "rail", "runway"]

Исключает перечисленные значения.


Условные выражения match

Оператор match позволяет сопоставлять значение с несколькими вариантами и задавать результат:

[
  "match",
  ["get", "type"],
  "restaurant", "#ff0000",
  "cafe", "#00ff00",
  "hotel", "#0000ff",
  "#999999"
]

Если type равен одному из перечисленных значений, возвращается соответствующий цвет. Последний аргумент — значение по умолчанию.


Условные выражения case

case работает как цепочка условий:

[
  "case",
  [">", ["get", "population"], 1000000], "#ff0000",
  [">", ["get", "population"], 500000], "#ffa500",
  "#00ff00"
]

Каждое условие проверяется по порядку. Возвращается первое истинное значение.


Фильтрация по свойствам объектов

Mapbox GL JS работает с данными GeoJSON и векторными тайлами, где свойства доступны через ["get", "property_name"].

map.addLayer({
  id: "cities",
  type: "circle",
  source: "places",
  filter: ["==", ["get", "class"], "city"]
});

Фильтр применяется до рендеринга, что делает его эффективнее, чем постобработка данных.


Изменение фильтра в рантайме

Фильтр слоя можно изменять динамически:

map.setFilter("cities", ["==", ["get", "class"], "capital"]);

Или сбросить фильтр:

map.setFilter("cities", null);

Изменение фильтра не требует перезагрузки источника данных.


Комбинирование фильтров

Фильтры можно вкладывать друг в друга:

[
  "all",
  ["==", ["get", "type"], "park"],
  [">", ["get", "area"], 10000],
  ["!=", ["get", "status"], "closed"]
]

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


Типы данных и особенности сравнения

Фильтры чувствительны к типам:

  • строки сравниваются строго
  • числа не приводятся автоматически
  • булевы значения должны быть явными (true / false)

Пример некорректного фильтра:

["==", ["get", "active"], "true"]

Если active — булево значение, правильный вариант:

["==", ["get", "active"], true]

Фильтрация GeoJSON-источников

При работе с GeoJSON фильтры применяются к каждому объекту Feature:

map.addSource("points", {
  type: "geojson",
  data: {
    type: "FeatureCollection",
    features: [
      {
        type: "Feature",
        properties: { category: "museum" },
        geometry: {
          type: "Point",
          coordinates: [37.6173, 55.7558]
        }
      }
    ]
  }
});
map.addLayer({
  id: "museums",
  type: "circle",
  source: "points",
  filter: ["==", ["get", "category"], "museum"]
});

Фильтрация векторных тайлов

Векторные тайлы содержат предагрегированные данные. Фильтры применяются к их свойствам аналогично GeoJSON:

map.addLayer({
  id: "roads",
  type: "line",
  source: "vector-source",
  "source-layer": "road",
  filter: ["in", ["get", "road_type"], "primary", "secondary"]
});

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


Взаимодействие с style expressions

Фильтры часто комбинируются с визуальными выражениями свойств слоя:

map.addLayer({
  id: "population",
  type: "circle",
  source: "cities",
  filter: [">", ["get", "population"], 100000],
  paint: {
    "circle-radius": [
      "interpolate",
      ["linear"],
      ["get", "population"],
      100000, 5,
      1000000, 20
    ],
    "circle-color": "#ff5722"
  }
});

Здесь фильтр ограничивает набор данных, а стиль отвечает за визуализацию оставшихся объектов.


Производительность фильтров

Фильтры Mapbox GL JS оптимизированы, но сложные выражения могут влиять на производительность:

  • глубокая вложенность all / any
  • частое использование case
  • фильтрация по вычисляемым выражениям вместо свойств

Рекомендуется:

  • хранить часто используемые признаки в свойствах GeoJSON
  • избегать вычислений в фильтрах
  • минимизировать количество условий

Динамическая сегментация данных

Фильтры часто используются для интерактивных сценариев:

  • переключение категорий объектов
  • отображение слоёв по уровню масштаба (в сочетании с minzoom / maxzoom)
  • выделение активных элементов интерфейса

Пример переключения категории:

function showCategory(category) {
  map.setFilter("places", ["==", ["get", "category"], category]);
}

Сложные примеры фильтрации

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

[
  "all",
  ["in", ["get", "type"], "restaurant", "cafe"],
  [">=", ["get", "rating"], 4],
  ["!=", ["get", "status"], "closed"]
]

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


Использование вложенных условий для классификации

[
  "case",
  [">", ["get", "speed"], 100], "highway",
  [">", ["get", "speed"], 50], "primary",
  "local"
]

Подобные конструкции часто применяются в сочетании с line-color или circle-color для тематической классификации данных.


Особенности отладки фильтров

Ошибки в фильтрах часто связаны с:

  • неверными именами свойств
  • несоответствием типов
  • неправильной структурой выражения

Типичный некорректный пример:

["==", "type", "park"]

Правильный вариант:

["==", ["get", "type"], "park"]

Маскирование данных через фильтры

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

map.setFilter("buildings", ["!=", ["get", "usage"], "residential"]);

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