Метод queryRenderedFeatures в MapLibre GL JS
используется для выборки объектов, которые в данный момент визуально
отрисованы на карте. Он работает поверх уже отрендеренного кадра WebGL,
поэтому возвращает только те данные, которые действительно видимы
пользователю с учётом стиля, масштаба, фильтров слоёв и текущего
viewport.
queryRenderedFeatures выполняет
пространственно-логический запрос к уже отрисованной сцене. Это
означает:
filter)beforeId)Метод не обращается напрямую к источникам данных как к хранилищу — он работает с результатом рендера, что делает его ключевым инструментом для интерактивности.
map.queryRenderedFeatures(point?, options?)
point (optional) Точка или прямоугольник области запроса:
{x, y} — пиксельная координатаBBox — массив [x1, y1, x2, y2]Если не передан, анализируется весь viewport.
options (optional)
{
layers?: string[],
filter?: array,
validate?: boolean
}
Параметр layers позволяет сузить поиск до конкретных
слоёв карты:
map.queryRenderedFeatures(event.point, {
layers: ['cities-layer', 'roads-layer']
});
Это критично для производительности при сложных стилях с десятками слоёв.
Фильтр работает в формате MapLibre Style Specification:
map.queryRenderedFeatures(event.point, {
filter: ['==', ['get', 'type'], 'restaurant']
});
Примеры выражений:
['==', ['get', 'id'], 10]['all', expr1, expr2]['>', ['get', 'population'], 100000]Фильтр применяется уже после рендеринга, что делает его мощным инструментом интерактивной аналитики.
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point);
console.log(features);
});
Возвращаемый массив содержит объекты:
{
type: 'Feature',
geometry: {...},
properties: {...},
layer: {...}
}
Каждый feature уже «привязан» к конкретному слою карты.
Наиболее частый сценарий — обработка кликов:
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['poi-layer']
});
if (features.length > 0) {
const feature = features[0];
console.log(feature.properties.name);
}
});
Пиксельная координата e.point является ключевым входом,
так как WebGL работает в экранных координатах, а не в
географических.
Для выделения объектов в области:
const bbox = [
startPoint.x,
startPoint.y,
endPoint.x,
endPoint.y
];
const features = map.queryRenderedFeatures(bbox, {
layers: ['buildings']
});
Такой подход используется в инструментах:
queryRenderedFeatures:
querySourceFeatures:
Пример различия:
map.queryRenderedFeatures(...); // только видимые объекты
map.querySourceFeatures('my-source'); // все доступные из source
Features возвращаются в порядке визуального наложения слоёв. Это важно:
При активной карте с большим количеством слоёв
queryRenderedFeatures может быть дорогой операцией.
Ключевые факторы оптимизации:
map.queryRenderedFeatures(point, {
layers: ['hotspots']
});
mousemove без throttle/debounceidle или render события
осторожноmap.queryRenderedFeatures(bbox)
быстрее, чем полный viewport-запрос без параметров.
Частый паттерн — подсветка объекта под курсором:
map.on('mousemove', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['countries']
});
map.getCanvas().style.cursor = features.length ? 'pointer' : '';
});
let selectedId = null;
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['regions']
});
if (!features.length) return;
selectedId = features[0].properties.id;
map.setFilter('regions-highlight', [
'==',
['get', 'id'],
selectedId
]);
});
При использовании кластеров (GeoJSON source with
cluster: true) queryRenderedFeatures
возвращает:
Пример:
map.queryRenderedFeatures(e.point, {
layers: ['clusters']
});
Дальнейшая работа часто включает:
map.getSource('points').getClusterExpansionZoom(clusterId);
Слои типа symbol могут возвращать несколько features на
одной пиксельной позиции:
Это приводит к ситуации, когда queryRenderedFeatures
возвращает несколько объектов для одного визуального элемента.
Хотя метод не принимает географические координаты напрямую, часто используется преобразование:
const point = map.project([lng, lat]);
const features = map.queryRenderedFeatures(point);
И обратное:
const lngLat = map.unproject(point);
Приводит к перегрузке и лишним данным:
map.queryRenderedFeatures(e.point);
Метод не предназначен для полного обхода данных.
Передача [lng, lat] вместо {x, y} приводит
к пустому результату.
queryRenderedFeatures часто используется как основа:
Типичный сценарий выделения:
const features = map.queryRenderedFeatures(e.point, {
layers: ['places']
});
if (features.length) {
const id = features[0].id;
map.setFeatureState(
{ source: 'places', id },
{ hover: true }
);
}
MapLibre рендерит данные через vector tiles. При запросе:
В стилях с большим количеством выражений
(expression-based styling) результат
queryRenderedFeatures уже содержит:
Это позволяет использовать метод как инструмент «визуальной семантики», а не только доступа к данным.