Фильтрация по свойствам

В MapLibre GL JS механизм фильтрации применяется на уровне слоёв и позволяет отображать только те объекты из источников данных, которые соответствуют заданным условиям. Фильтр описывается через выражения (expressions) и задаётся в свойстве filter слоя.

Фильтрация тесно связана с моделью данных GeoJSON и векторных тайлов, где каждый объект содержит набор свойств (properties). Именно эти свойства становятся основой для логических условий отображения.


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

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

map.addLayer({
  id: 'cities-layer',
  type: 'circle',
  source: 'cities',
  paint: {
    'circle-radius': 6,
    'circle-color': '#2b8cbe'
  },
  filter: ['==', ['get', 'type'], 'city']
});

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

Ключевые элементы:

  • ['get', 'type'] — извлечение свойства объекта
  • '==' — оператор сравнения
  • 'city' — значение для сравнения

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

Фильтрация в MapLibre GL JS опирается на выражения, аналогичные Mapbox Style Specification.

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

filter: ['==', ['get', 'class'], 'primary']

Отображает объекты с class = primary.

filter: ['!=', ['get', 'class'], 'secondary']

Исключает объекты с class = secondary.


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

filter: ['>', ['get', 'population'], 1000000]

Показывает города с населением больше 1 млн.

filter: ['>=', ['get', 'rank'], 10]

Включает объекты с рангом 10 и выше.

filter: ['<', ['get', 'elevation'], 500]

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

filter: ['<=', ['get', 'score'], 50]

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

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

filter: ['has', 'name']

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

Обратная логика:

filter: ['!', ['has', 'name']]

Отбирает объекты без свойства name.


Работа с множественными значениями

Оператор in

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

filter: ['in', ['get', 'type'], 'city', 'town', 'village']

Альтернативная форма:

filter: ['in', 'city', ['get', 'type']]

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

Фильтрация часто требует комбинирования условий.

AND (all)

filter: [
  'all',
  ['==', ['get', 'type'], 'city'],
  ['>', ['get', 'population'], 500000]
]

Отображает только крупные города.


OR (any)

filter: [
  'any',
  ['==', ['get', 'capital'], true],
  ['>', ['get', 'population'], 1000000]
]

Объекты, которые являются столицами или имеют большую численность населения.


NOT (none)

filter: [
  'none',
  ['==', ['get', 'status'], 'inactive']
]

Исключение всех неактивных объектов.


Вложенные условия и композиция фильтров

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

filter: [
  'all',
  ['any',
    ['==', ['get', 'type'], 'city'],
    ['==', ['get', 'type'], 'town']
  ],
  ['>=', ['get', 'population'], 100000],
  ['!=', ['get', 'status'], 'deprecated']
]

Логика:

  • объект должен быть городом или посёлком
  • население не менее 100 000
  • статус не должен быть deprecated

Фильтрация по строковым шаблонам

Для работы со строками используются операторы:

== и точные совпадения

filter: ['==', ['get', 'country'], 'Kazakhstan']

!= и исключение значений

filter: ['!=', ['get', 'region'], 'excluded-region']

match — сопоставление с несколькими значениями

filter: [
  'match',
  ['get', 'type'],
  ['city', 'town', 'village'],
  true,
  false
]

Если type входит в список — true, иначе false.


Фильтрация числовых диапазонов

Часто используется ограничение диапазона значений:

filter: [
  'all',
  ['>=', ['get', 'population'], 10000],
  ['<', ['get', 'population'], 50000]
]

Отбор объектов среднего размера.


Динамическое управление фильтрами

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

map.setFilter('cities-layer', [
  '>', ['get', 'population'], 100000
]);

Сброс фильтра:

map.setFilter('cities-layer', null);

Удаление фильтра возвращает отображение всех объектов слоя.


Фильтрация в зависимости от масштаба карты

Хотя напрямую масштаб не является свойством объектов, его можно учитывать через состояние карты:

map.on('zoom', () => {
  const zoom = map.getZoom();

  if (zoom > 10) {
    map.setFilter('cities-layer', ['>=', ['get', 'population'], 50000]);
  } else {
    map.setFilter('cities-layer', ['>=', ['get', 'population'], 500000]);
  }
});

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


Использование фильтрации с типами слоёв

Фильтры работают с различными типами слоёв:

  • circle — точки
  • line — линии
  • fill — полигоны
  • symbol — подписи и иконки

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

map.addLayer({
  id: 'roads',
  type: 'line',
  source: 'transport',
  paint: {
    'line-color': '#ff6600',
    'line-width': 2
  },
  filter: ['==', ['get', 'highway'], 'primary']
});

Фильтрация геометрических классов объектов

Часто используется разделение по типам геометрии или категории объектов:

filter: ['==', ['geometry-type'], 'Polygon']

или

filter: ['==', ['geometry-type'], 'Point']

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


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

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

Факторы влияния:

  • количество условий в all / any
  • глубина вложенности выражений
  • частота обновления фильтра через setFilter
  • объём источника данных

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

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

Совмещение фильтрации и стилей

Фильтрация часто используется совместно с выражениями стилей (paint, layout), создавая многослойную визуализацию одного источника.

map.addLayer({
  id: 'population-based-cities',
  type: 'circle',
  source: 'cities',
  paint: {
    'circle-radius': [
      'interpolate',
      ['linear'],
      ['get', 'population'],
      1000, 3,
      1000000, 10
    ],
    'circle-color': [
      'case',
      ['>', ['get', 'population'], 1000000],
      '#e31a1c',
      '#3182bd'
    ]
  },
  filter: ['>=', ['get', 'population'], 1000]
});

Здесь фильтр задаёт базовый диапазон объектов, а стиль дополнительно уточняет визуальное представление.


Комбинирование нескольких слоёв с разными фильтрами

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

map.addLayer({
  id: 'cities-large',
  type: 'circle',
  source: 'cities',
  filter: ['>', ['get', 'population'], 1000000]
});

map.addLayer({
  id: 'cities-medium',
  type: 'circle',
  source: 'cities',
  filter: [
    'all',
    ['<=', ['get', 'population'], 1000000],
    ['>', ['get', 'population'], 100000]
  ]
});

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