Выделение объектов в OpenLayers строится вокруг концепции
интерактивных слоёв и векторных объектов, где ключевым элементом
выступает механизм определения попадания курсора в геометрию. Базовая
единица — объект Feature, размещённый в
VectorSource и визуализируемый через
VectorLayer.
Процесс выбора опирается на две основные стратегии:
filter, condition,
layersЦентральным инструментом выделения является Select из
модуля взаимодействий:
import Select fr om 'ol/interaction/Sel ect.js';
import {click} fr om 'ol/events/condition.js';
Конфигурация базового выделения:
const sel ect = new Select({
condition: click
});
map.addInteraction(select);
Событие выбора формируется при попадании клика в геометрию
Feature. Внутри взаимодействия поддерживается коллекция
выбранных объектов, доступная через:
select.getFeatures()
Эта коллекция является реактивной и может использоваться для синхронизации состояния интерфейса.
Механизм condition определяет событие, которое
инициирует выбор:
click — выбор по кликуpointerMove — выбор при наведенииsingleClick — одиночный клик без dblclickПример выбора при наведении:
import {pointerMove} fr om 'ol/events/condition.js';
const sel ect = new Select({
condition: pointerMove
});
Условия можно комбинировать через логические функции, формируя сложные сценарии взаимодействия.
Для работы с несколькими объектами используются параметры:
const select = new Select({
multi: true
});
Дополнительные механизмы:
toggleCondition — переключение состояния объектаaddCondition — добавление в выборremoveCondition — удаление из выбораПример с клавишей Shift:
import {shiftKeyOnly} fr om 'ol/events/condition.js';
const sel ect = new Select({
condition: click,
toggleCondition: shiftKeyOnly
});
Выбор может быть ограничен логикой фильтрации через
filter:
const select = new Select({
filter: function(feature, layer) {
return feature.get('selectable') === true;
}
});
Фильтрация используется для:
Параметр layers позволяет задать список допустимых
слоёв:
const select = new Select({
layers: function(layer) {
return layer.get('interactive') === true;
}
});
Такой подход отделяет интерактивные слои от визуальных или служебных.
Одним из ключевых аспектов является визуальное выделение через
style.
const select = new Select({
style: function(feature) {
return new Style({
stroke: new Stroke({
color: 'red',
width: 2
}),
fill: new Fill({
color: 'rgba(255,0,0,0.2)'
})
});
}
});
Стиль применяется только к выбранным объектам, не изменяя исходный стиль слоя.
Выбранные объекты хранятся в коллекции:
const features = select.getFeatures();
Основные операции:
features.push(feature)features.remove(feature)features.clear()События коллекции позволяют отслеживать изменения:
features.on('add', function(e) {});
features.on('remove', function(e) {});
Выделение может выполняться без пользовательского взаимодействия:
const feature = vectorSource.getFeatureById(1);
select.getFeatures().push(feature);
Очистка выделения:
select.getFeatures().clear();
Альтернативный способ — прямой hit-test через карту:
map.forEachFeatureAtPixel(pixel, function(feature, layer) {
console.log(feature);
});
Либо более точный вариант:
map.getFeaturesAtPixel(pixel);
Этот подход используется для кастомных механизмов выбора и сложных UI-сценариев.
Параметр hitTolerance расширяет область клика:
const select = new Select({
hitTolerance: 10
});
Применяется при:
Дополнительный инструмент выделения — прямоугольная рамка:
import DragBox fr om 'ol/interaction/DragBox.js';
Пример логики:
const dragBox = new DragBox();
dragBox.on('boxend', function() {
const extent = dragBox.getGeometry().getExtent();
vectorSource.forEachFeatureIntersectingExtent(extent, function(feature) {
select.getFeatures().push(feature);
});
});
Этот механизм применяется для массового выбора.
При использовании кластеризации (Cluster source) выбор
требует работы с внутренними элементами:
feature.get('features')
Кластер представляет собой агрегированный объект, внутри которого
находится массив исходных Feature.
Логика выбора:
Select взаимодействие генерирует события:
select — изменение состояния выбораchange — модификация коллекцииПример:
select.on('select', function(e) {
console.log(e.selected);
console.log(e.deselected);
});
Структура события включает:
Состояние выбора может сериализоваться через идентификаторы:
const ids = select.getFeatures().getArray().map(f => f.getId());
Восстановление:
ids.forEach(id => {
const feature = source.getFeatureById(id);
select.getFeatures().push(feature);
});
При работе с тысячами объектов критичны следующие факторы:
SpatialIndex внутри источникаforEachFeatureAtPixelОптимизация hit-test часто важнее оптимизации рендера.
Сложные сценарии реализуются через комбинирование:
SelectDragBoxforEachFeatureAtPixelПример гибридного подхода:
const select = new Select({
condition: click,
filter: feature => feature.getGeometry().getType() === 'Point'
});
Контроль состояния осуществляется вручную:
if (select.getFeatures().getLength() > 0) {
select.getFeatures().clear();
}
Либо через toggle-логику:
if (features.getArray().includes(feature)) {
features.remove(feature);
} else {
features.push(feature);
}