Выделение объектов — один из ключевых механизмов интерактивных геоинформационных приложений на базе CesiumJS. Пользователь может выбирать здания, точки интереса, модели, геометрические примитивы и другие сущности, получая дополнительную информацию или возможность дальнейшего взаимодействия.
В CesiumJS выделение обычно реализуется через:
Механизм выделения применяется в системах мониторинга, цифровых двойниках, военных ГИС, навигационных сервисах и инженерных платформах.
Для определения объекта под указателем используется метод
scene.pick().
const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);
handler.setInputAction(function(movement) {
const pickedObject = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(pickedObject)) {
console.log("Объект найден");
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
Метод анализирует содержимое сцены в указанной экранной точке и возвращает найденный объект.
Параметр:
movement.endPosition
содержит координаты курсора в пикселях относительно окна визуализации.
Наиболее распространённый сценарий — выбор объекта левым кликом.
handler.setInputAction(function(click) {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
console.log("Объект выбран");
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
После выполнения pick() можно определить, какой именно
объект был выбран.
Если объект создан через API сущностей, доступ к нему можно получить
через свойство id.
handler.setInputAction(function(click) {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
const entity = pickedObject.id;
console.log(entity.name);
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Пример создания сущности:
const city = viewer.entities.add({
name: "Москва",
position: Cesium.Cartesian3.fromDegrees(37.6176, 55.7558),
point: {
pixelSize: 12,
color: Cesium.Color.RED
}
});
После выбора можно получить:
entity.name
entity.position
entity.description
entity.properties
Viewer предоставляет встроенный механизм выбора.
viewer.selectedEntity = entity;
После присвоения:
Пример:
handler.setInputAction(function(click) {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject)) {
viewer.selectedEntity = pickedObject.id;
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Для отображения информации используется свойство
description.
viewer.entities.add({
name: "Башня",
description: `
<h2>Башня связи</h2>
<p>Высота: 120 м</p>
<p>Год постройки: 2015</p>
`,
position: position,
point: {
pixelSize: 10
}
});
После выбора объект автоматически отображается в панели информации.
Один из самых распространённых способов выделения — изменение цвета.
Исходный объект:
const building = viewer.entities.add({
polygon: {
hierarchy: positions,
material: Cesium.Color.BLUE
}
});
Выделение:
building.polygon.material = Cesium.Color.YELLOW;
Снятие выделения:
building.polygon.material = Cesium.Color.BLUE;
При выборе нового объекта обычно требуется восстановить внешний вид предыдущего.
let selectedEntity = null;
handler.setInputAction(function(click) {
const picked = viewer.scene.pick(click.position);
if (!Cesium.defined(picked)) {
return;
}
if (selectedEntity) {
selectedEntity.point.color =
Cesium.Color.RED;
}
selectedEntity = picked.id;
selectedEntity.point.color =
Cesium.Color.YELLOW;
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Такой подход предотвращает накопление множества визуально выделенных объектов.
Для точечных объектов часто изменяются:
Пример:
entity.point.color = Cesium.Color.YELLOW;
entity.point.pixelSize = 20;
entity.point.outlineColor =
Cesium.Color.BLACK;
entity.point.outlineWidth = 3;
До выбора:
point: {
pixelSize: 10,
color: Cesium.Color.RED
}
После выбора:
point: {
pixelSize: 20,
color: Cesium.Color.YELLOW,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 3
}
Для линий удобно изменять толщину и цвет.
Исходное состояние:
polyline: {
positions: positions,
width: 3,
material: Cesium.Color.BLUE
}
После выбора:
entity.polyline.width = 8;
entity.polyline.material =
Cesium.Color.YELLOW;
Это делает выбранный маршрут или коммуникацию значительно заметнее.
Для полигонов обычно используются:
Пример:
entity.polygon.material =
Cesium.Color.YELLOW.withAlpha(0.7);
Добавление контура:
entity.polygon.outline = true;
entity.polygon.outlineColor =
Cesium.Color.BLACK;
Выделение не всегда связано с выбором. Часто используется режим наведения курсора.
let highlightedEntity = null;
handler.setInputAction(function(movement) {
if (highlightedEntity) {
highlightedEntity.point.color =
Cesium.Color.RED;
highlightedEntity = null;
}
const picked =
viewer.scene.pick(movement.endPosition);
if (Cesium.defined(picked)) {
highlightedEntity = picked.id;
highlightedEntity.point.color =
Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
Подобное поведение напоминает интерфейсы настольных ГИС.
Для наборов 3D Tiles применяется иной подход.
const pickedFeature =
viewer.scene.pick(click.position);
Если найден объект тайлов:
if (pickedFeature instanceof Cesium.Cesium3DTileFeature) {
}
Подсветка выполняется через свойство color.
pickedFeature.color =
Cesium.Color.YELLOW;
Пример:
handler.setInputAction(function(click) {
const feature =
viewer.scene.pick(click.position);
if (feature instanceof Cesium.Cesium3DTileFeature) {
feature.color =
Cesium.Color.YELLOW;
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Необходимо сохранять исходное состояние.
let selectedFeature;
let originalColor;
Выбор:
if (selectedFeature) {
selectedFeature.color = originalColor;
}
Сохранение цвета:
selectedFeature = feature;
originalColor =
Cesium.Color.clone(feature.color);
Новое выделение:
feature.color =
Cesium.Color.YELLOW;
Cesium поддерживает постобработку контуров.
Создание стадии:
const silhouette =
Cesium.PostProcessStageLibrary
.createEdgeDetectionStage();
Настройка:
silhouette.uniforms.color =
Cesium.Color.YELLOW;
silhouette.uniforms.length = 0.02;
Добавление:
viewer.scene.postProcessStages
.add(silhouette);
Назначение объектов:
silhouette.selected = [feature];
Результат — вокруг объекта появляется яркий контур.
Специальная стадия:
const silhouetteStage =
Cesium.PostProcessStageLibrary
.createSilhouetteStage();
Подключение:
viewer.scene.postProcessStages
.add(silhouetteStage);
Выбор объекта:
silhouetteStage.selected = [pickedObject];
Подобный вариант особенно полезен для сложных моделей.
Для моделей формата glTF выбор производится аналогично.
Создание модели:
viewer.entities.add({
position: position,
model: {
uri: "model.glb"
}
});
Выбор:
const picked =
viewer.scene.pick(click.position);
Получение сущности:
const entity = picked.id;
Выделение:
entity.model.color =
Cesium.Color.YELLOW;
Настройка прозрачности:
entity.model.color =
Cesium.Color.YELLOW.withAlpha(0.8);
Для более заметной подсветки применяется режим смешивания.
entity.model.colorBlendMode =
Cesium.ColorBlendMode.MIX;
Интенсивность:
entity.model.colorBlendAmount = 0.8;
Цвет выделения:
entity.model.color =
Cesium.Color.YELLOW;
Иногда требуется выбрать сразу несколько объектов.
Хранилище:
const selectedObjects = [];
Добавление:
selectedObjects.push(entity);
Выделение:
entity.point.color =
Cesium.Color.YELLOW;
Снятие выделения со всех объектов:
selectedObjects.forEach(entity => {
entity.point.color =
Cesium.Color.RED;
});
Очистка:
selectedObjects.length = 0;
Для выбора группы объектов применяется прямоугольная область.
Общая схема:
Экранные координаты объектов вычисляются через:
Cesium.SceneTransforms
.wgs84ToWindowCoordinates(
viewer.scene,
position
);
После чего проверяется попадание точки внутрь прямоугольника.
Часто требуется хранить состояние выбора непосредственно внутри объекта.
entity.properties = new Cesium.PropertyBag({
selected: false
});
При выборе:
entity.properties.selected = true;
Проверка:
if (entity.properties.selected) {
}
Такой подход упрощает организацию логики больших приложений.
Щелчок по пустой области сцены может использоваться для очистки выбора.
handler.setInputAction(function(click) {
const picked =
viewer.scene.pick(click.position);
if (!Cesium.defined(picked)) {
viewer.selectedEntity = null;
return;
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
Очистка пользовательской подсветки:
if (selectedEntity) {
selectedEntity.point.color =
Cesium.Color.RED;
selectedEntity = null;
}
При работе с десятками тысяч объектов необходимо учитывать ряд особенностей:
pick();Особенно эффективно использование контурной постобработки, поскольку визуальное выделение создаётся средствами графического процессора без изменения самих данных сцены.
Типичная структура крупного приложения включает следующие компоненты:
SelectionManager
HighlightManager
PickController
scene.pick();InfoPanel
Подобная архитектура позволяет одинаково работать с сущностями, моделями glTF, примитивами и объектами 3D Tiles, обеспечивая единый механизм выделения во всём приложении.