Механизм запроса отрисованных объектов в MapLibre GL JS позволяет получать геометрии и свойства тех слоёв карты, которые уже прошли этап рендеринга и находятся в текущем видимом состоянии. Это ключевой инструмент для интерактивности: определение объектов под курсором, обработка кликов, построение всплывающих карточек, выделение элементов и реализация логики выбора.
В отличие от запросов к исходным данным источника
(source), данный подход работает исключительно с тем, что
уже попало в текущий кадр карты, включая учёт стилей, фильтров слоёв,
видимости и масштаба.
Основная точка входа — метод:
map.queryRenderedFeatures(...)
Метод поддерживает несколько вариантов вызова в зависимости от задачи:
map.queryRenderedFeatures(point?, options?)
map.queryRenderedFeatures(bbox?, options?)
Используется для получения объектов под конкретным пикселем:
const features = map.queryRenderedFeatures(
[x, y],
{ layers: ['cities', 'roads'] }
);
Используется для получения всех объектов в прямоугольной зоне:
const features = map.queryRenderedFeatures(
[[x1, y1], [x2, y2]],
{ layers: ['buildings'] }
);
Координаты всегда задаются в экранных пикселях относительно контейнера карты. Это важно: используются не географические координаты, а координаты viewport.
map.on('click', (e) => {
const features = map.queryRenderedFeatures(e.point);
});
Значение e.point уже нормализовано и готово для
использования.
Прямоугольная область задаётся двумя точками:
const bbox = [
[100, 100],
[300, 300]
];
const features = map.queryRenderedFeatures(bbox);
Этот режим применяется для выделения множества объектов, например при drag-selection.
Наиболее важный параметр — ограничение поиска слоями:
map.queryRenderedFeatures(point, {
layers: ['water', 'landuse']
});
Если параметр layers не указан, будут возвращены объекты
со всех видимых слоёв, что может сильно повлиять на
производительность.
Можно дополнительно уточнять выборку через filter:
map.queryRenderedFeatures(point, {
layers: ['cities'],
filter: ['==', ['get', 'type'], 'capital']
});
Фильтр использует выражения MapLibre Style Specification и выполняется уже на уровне рендеринга.
Метод возвращает массив объектов Feature, каждый из
которых содержит:
geometry — геометрия (Point, LineString, Polygon)properties — свойства из источника данныхlayer — информация о стиле слояsource — идентификатор источника данныхsourceLayer — имя слоя внутри vector tile (если
применимо)state — состояние feature-state (если
используется)Пример структуры:
{
type: 'Feature',
geometry: { type: 'Point', coordinates: [...] },
properties: { name: 'City A' },
layer: { id: 'cities-layer', type: 'circle' },
source: 'places'
}
Результаты возвращаются в порядке визуального наложения слоёв: сверху вниз. Это означает, что верхние слои в стиле карты будут первыми в массиве.
Это поведение критично для реализации:
Запрос учитывает:
visibility: none (слой исключается)minzoom / maxzoomТаким образом, объект может существовать в источнике, но не попадать в результат, если он не отрисован.
Существует принципиальное различие между двумя методами:
Наиболее частый сценарий — события мыши:
map.on('mousemove', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['roads']
});
map.getCanvas().style.cursor = features.length ? 'pointer' : '';
});
Применение:
При наличии сложной композиции слоёв важно ограничивать запрос:
const features = map.queryRenderedFeatures(point, {
layers: ['buildings-fill', 'buildings-outline']
});
Без ограничения возможны:
Запрос отрисованных объектов может быть дорогим при:
Рекомендации:
layersmap.on('click', (e) => {
const feature = map.queryRenderedFeatures(e.point, {
layers: ['pois']
})[0];
});
Используется для получения одного «верхнего» объекта.
const features = map.queryRenderedFeatures(selectionBox, {
layers: ['buildings']
});
Позволяет реализовать выделение множества объектов.
map.on('mousemove', (e) => {
const features = map.queryRenderedFeatures(e.point, {
layers: ['roads']
});
if (features.length) {
map.setFeatureState(features[0], { hover: true });
}
});
При использовании vector tiles следует учитывать:
Это влияет на стабильность идентификации объектов без
id.
Приводит к неожиданным результатам и падению производительности.
Объекты могут исчезать из результата при смене масштаба.
Порядок зависит от стиля, а не от источника данных.
При использовании:
map.setFeatureState({ source, id }, { selected: true });
queryRenderedFeatures может возвращать объект, но
состояние нужно проверять отдельно через feature-state, а
не через properties.
Комбинация событий и запроса:
queryRenderedFeaturesЭтот цикл является основой большинства интерактивных картографических интерфейсов в MapLibre GL JS.