Фильтрация данных в Mapbox GL JS является одним из ключевых механизмов управления отображением векторных слоёв, позволяющим динамически контролировать видимость объектов на карте без изменения исходного источника данных.
Основной принцип фильтрации заключается в применении выражений
(filter expressions) к слоям карты. Каждый слой может содержать правило
filter, которое определяет, какие фичи из источника будут
визуализированы. Фильтры применяются на уровне слоя и не изменяют
исходный набор данных, что делает их эффективным инструментом для
интерактивных приложений.
Фильтр слоя задаётся в объекте слоя и представляет собой массив, где первый элемент — оператор, а последующие — аргументы:
map.addLayer({
id: 'cities-layer',
type: 'circle',
source: 'cities',
'source-layer': 'cities-data',
filter: ['==', 'type', 'city']
});
В данном случае отображаются только те объекты, у которых свойство
type равно city.
Фильтры в Mapbox GL JS используют выражения, основанные на логике S-expression. Это обеспечивает гибкость и читаемость.
['==', 'property', value] // равенство
['!=', 'property', value] // не равно
['>', 'property', value] // больше
['>=', 'property', value] // больше или равно
['<', 'property', value] // меньше
['<=', 'property', value] // меньше или равно
Пример фильтрации объектов по числовому полю:
filter: ['>=', 'population', 1000000]
Отображаются только города с населением более одного миллиона.
Для построения сложных условий используются логические операторы:
['all', expr1, expr2, ...] // И
['any', expr1, expr2, ...] // ИЛИ
['none', expr1, expr2, ...] // НЕ (ни одно условие)
Пример комбинированного фильтра:
filter: [
'all',
['==', 'type', 'city'],
['>=', 'population', 500000]
]
Mapbox GL JS поддерживает проверку вхождения значений в список.
infilter: ['in', 'country', 'KZ', 'RU', 'UZ']
Фильтрует объекты, принадлежащие указанным странам.
filter: ['has', 'name']
Отображаются только объекты, у которых существует свойство
name.
filter: ['!', ['has', 'population']]
Отбираются объекты без поля population.
Фильтрация может учитывать тип геометрии:
filter: ['==', '$type', 'Point']
Доступные значения:
PointLineStringPolygonЭто позволяет разделять отображение различных типов объектов из одного источника.
Одним из наиболее мощных механизмов является динамическое обновление
фильтров через метод setFilter.
map.setFilter('cities-layer', ['>=', 'population', 1000000]);
Фильтр применяется мгновенно без перезагрузки источника данных.
function updateFilter(minPopulation) {
map.setFilter('cities-layer', [
'>=',
'population',
minPopulation
]);
}
Такой подход используется в интерфейсах с ползунками, чекбоксами и поисковыми полями.
caseДля более сложной логики используется выражение case,
позволяющее задавать цепочку условий:
filter: [
'case',
['>=', 'population', 1000000],
true,
false
]
Хотя такой подход чаще применяется в стилях, он также может использоваться в фильтрах для формирования логических ветвлений.
Строковые фильтры часто применяются для категорий:
filter: ['==', 'category', 'park']
или:
filter: ['in', 'category', 'park', 'forest', 'lake']
Это основной способ сегментации данных в тематических слоях.
Фильтрация строк чувствительна к регистру. Это требует предварительной нормализации данных или использования выражений преобразования:
filter: ['==', ['downcase', ['get', 'name']], 'almaty']
Такой подход позволяет унифицировать сравнение строковых значений.
Фильтры могут зависеть от уровня масштаба, но чаще это реализуется
через zoom-based styling. Тем не менее, комбинированный
подход возможен:
filter: [
'all',
['>=', ['zoom'], 5],
['<=', ['zoom'], 10]
]
Хотя чаще масштаб контролируется через minzoom и
maxzoom слоя, фильтрация позволяет более тонкую настройку
логики отображения.
При использовании GeoJSON фильтрация применяется к каждому объекту в источнике:
map.addSource('points', {
type: 'geojson',
data: '/data/points.geojson'
});
map.addLayer({
id: 'points-layer',
type: 'circle',
source: 'points',
filter: ['==', ['get', 'active'], true]
});
Здесь используется выражение ['get', 'active'],
позволяющее извлекать свойства объектов.
Фильтры могут включать арифметические и логические операции:
filter: [
'>',
['+', ['get', 'a'], ['get', 'b']],
10
]
Такой подход позволяет создавать вычисляемые условия без предварительной обработки данных.
Фильтрация часто используется для:
Пример сегментации по типу:
const types = ['school', 'hospital', 'shop'];
types.forEach(type => {
map.addLayer({
id: `${type}-layer`,
type: 'circle',
source: 'places',
filter: ['==', 'type', type]
});
});
Фильтрация выполняется на уровне рендеринга WebGL и оптимизирована для работы с большими наборами данных. Однако сложные выражения могут влиять на производительность.
Критические факторы:
setFilterОптимизация достигается за счёт:
Фильтры применяются только к данным, уже загруженным в источник. Они не заменяют серверную фильтрацию и не уменьшают объём передаваемых данных.
Также фильтры:
Фильтрация тесно связана со стилями отображения. Часто один и тот же атрибут используется одновременно в фильтре и в стиле:
map.addLayer({
id: 'roads',
type: 'line',
source: 'transport',
filter: ['==', 'highway', 'primary'],
paint: {
'line-width': 2,
'line-color': '#ff0000'
}
});
Это обеспечивает согласованное поведение визуализации и логики отбора данных.