Управление состоянием карты в OpenLayers опирается на связку объектов
Map, View, слоёв, источников данных и
событийной модели Observable. Состояние карты в данном
контексте — это совокупность параметров, определяющих текущее
отображение и поведение: координаты центра, масштаб, поворот, видимость
слоёв, параметры источников, активные взаимодействия и пользовательские
настройки интерфейса.
Основной носитель визуального состояния — объект
ol/View. Он инкапсулирует параметры, которые напрямую
влияют на отображение:
center)zoom)resolution)projection)rotation)Изменение любого из этих параметров приводит к перерасчёту отображения слоя и перерисовке карты.
Ключевые методы управления состоянием:
setCenter(coordinate) — установка центраsetZoom(level) — изменение масштабаsetRotation(angle) — поворот картыsetResolution(resolution) — прямое управление
разрешениемПример программного изменения состояния:
view.setCenter([4180000, 7500000]);
view.setZoom(6);
view.setRotation(0);
Получение текущего состояния осуществляется через соответствующие геттеры:
const center = view.getCenter();
const zoom = view.getZoom();
const rotation = view.getRotation();
Важной особенностью является то, что View является
реактивным объектом: изменения немедленно транслируются в систему
рендеринга карты.
Состояние карты в OpenLayers тесно связано с системой событий. Все
ключевые объекты наследуют ol/Observable, что позволяет
отслеживать изменения.
Основные события, влияющие на состояние:
moveend — завершение перемещения картыchange:center — изменение центраchange:resolution — изменение масштаба/разрешенияchange:rotation — изменение поворотаpropertychange — изменение любого свойстваПример отслеживания изменения положения карты:
view.on('change:center', () => {
const center = view.getCenter();
});
Для отслеживания завершения интерактивных изменений используется:
map.on('moveend', () => {
const view = map.getView();
const state = {
center: view.getCenter(),
zoom: view.getZoom(),
rotation: view.getRotation()
};
});
Событие moveend особенно важно при синхронизации
состояния с внешними системами хранения или URL.
Объект ol/Map агрегирует состояние представления, слоёв
и взаимодействий. Он не хранит географическое состояние напрямую, но
управляет связями между компонентами.
Ключевые аспекты состояния Map:
layer collection)Viewinteractions)controls)size)Слои хранят собственное состояние видимости и порядка отображения:
layer.setVisible(true);
layer.setZIndex(10);
Состояние коллекции слоёв является реактивным:
map.getLayers().on('add', (event) => {
const layer = event.element;
});
Каждый слой (ol/layer/Tile,
ol/layer/Vector) содержит внутреннее состояние, влияющее на
отображение:
visible)opacity)zIndex)source)Источники данных (ol/source) также имеют состояние
загрузки и кэширования:
Пример управления состоянием слоя:
layer.setVisible(false);
layer.setOpacity(0.5);
layer.setZIndex(5);
Для векторных источников:
vectorSource.clear();
vectorSource.addFeature(feature);
Изменение источника данных фактически перестраивает визуальное состояние слоя.
Слои и источники поддерживают событийную модель:
layer.on('change:visible', () => {
const visible = layer.getVisible();
});
Для источников:
vectorSource.on('addfeature', (event) => {
const feature = event.feature;
});
Эти события позволяют строить систему синхронизации состояния между данными и интерфейсом.
Одним из ключевых аспектов является сохранение и восстановление состояния. Типичная структура состояния включает:
Сериализация состояния:
const state = {
center: view.getCenter(),
zoom: view.getZoom(),
rotation: view.getRotation(),
layers: map.getLayers().getArray().map(l => ({
visible: l.getVisible(),
opacity: l.getOpacity()
}))
};
Восстановление состояния:
view.setCenter(state.center);
view.setZoom(state.zoom);
view.setRotation(state.rotation);
state.layers.forEach((lState, i) => {
const layer = map.getLayers().item(i);
layer.setVisible(lState.visible);
layer.setOpacity(lState.opacity);
});
Подобный подход формирует базу для клиентского persistence без привязки к серверу.
Распространённый подход — кодирование состояния в URL. Это позволяет сохранять:
Пример формирования URL-параметров:
const params = new URLSearchParams();
params.set('c', view.getCenter().join(','));
params.set('z', view.getZoom());
params.set('r', view.getRotation());
window.location.hash = params.toString();
Восстановление:
const params = new URLSearchParams(window.location.hash.slice(1));
const center = params.get('c')?.split(',').map(Number);
const zoom = Number(params.get('z'));
const rotation = Number(params.get('r'));
if (center) view.setCenter(center);
if (!isNaN(zoom)) view.setZoom(zoom);
if (!isNaN(rotation)) view.setRotation(rotation);
Такой подход превращает карту в адресуемое состояние, пригодное для шаринга.
При построении сложных приложений поверх OpenLayers часто используется подход, при котором состояние карты хранится отдельно от объектов библиотеки.
Схема:
ViewПример логики синхронизации:
store.subscribe((state) => {
const view = map.getView();
view.setCenter(state.center);
view.setZoom(state.zoom);
});
И обратная синхронизация:
view.on('moveend', () => {
store.dispatch({
type: 'MAP_UPDATED',
center: view.getCenter(),
zoom: view.getZoom()
});
});
Подобный подход предотвращает расхождение состояния между UI и картой.
Взаимодействия (ol/interaction) также являются частью
состояния карты:
Каждое взаимодействие можно включать и выключать:
selectInteraction.setActive(false);
drawInteraction.setActive(true);
Состояние взаимодействий часто зависит от режима приложения (просмотр, редактирование, анализ).
Коллекция взаимодействий также реактивна:
map.getInteractions().forEach((interaction) => {
interaction.setActive(false);
});
Карта имеет внутреннее состояние рендеринга, которое отслеживается через события:
precomposepostcomposerendercompleteПример отслеживания завершения отрисовки:
map.on('rendercomplete', () => {
const canvas = map.getViewport().querySelector('canvas');
});
Это состояние используется для создания снимков карты и синхронизации визуального результата.
Изменение большинства параметров автоматически вызывает перерасчёт отображения. Однако иногда требуется принудительная инвалидация:
map.render();
или
layer.changed();
Это переводит объект в состояние, требующее повторного рендеринга.
Состояние OpenLayers формируется на нескольких уровнях:
Эта иерархия создаёт многослойную модель, в которой изменения на нижнем уровне могут каскадно влиять на верхние уровни.
При динамических данных (например, потоковые обновления) состояние карты становится непрерывно изменяющимся процессом.
Типичная схема:
addFeature,
removeFeature)Пример обновления:
setInterval(() => {
const feature = new Feature({
geometry: new Point([Math.random() * 1e6, Math.random() * 1e6])
});
vectorSource.addFeature(feature);
}, 1000);
Такой режим формирует потоковое состояние, в котором карта выступает визуализатором изменяющейся модели данных.