В основе архитектуры OpenLayers лежит система наблюдаемых объектов
(ol/Observable) и событий, через которую реализуются все
точки расширения поведения. В отличие от классических «хуков» в
UI-фреймворках, здесь под хуками фактически понимаются события
жизненного цикла карты, слоёв, источников данных, взаимодействий и
рендеринга.
Каждый ключевой объект библиотеки — карта, представление, слой,
источник данных, интеракция — наследует поведение наблюдаемого объекта и
предоставляет механизм подписки на события через on,
once, un.
Ключевая особенность: система событий не является вспомогательной надстройкой, а представляет собой основной способ управления состоянием и реакциями системы.
Базовый класс ol/Observable реализует паттерн
наблюдателя. Любой объект, наследующий его, становится источником
событий.
Подписка на события:
map.on('click', function (event) {
console.log(event.coordinate);
});
Одноразовая подписка:
map.once('rendercomplete', function () {
console.log('Первый завершённый рендер');
});
Удаление обработчика:
function handler(e) {
console.log(e);
}
map.on('moveend', handler);
map.un('moveend', handler);
События в OpenLayers не просто уведомления, а структурированные объекты, содержащие контекст: координаты, пиксели, состояние слоя, текущее представление карты.
Объект ol/Map является центральным источником событий,
отражающих весь цикл работы визуализации.
postrender и prerender
Эти события относятся к WebGL / Canvas-пайплайну рендеринга:
map.on('postrender', function (event) {
const frameState = event.frameState;
});
frameState содержит текущее состояние сцены: масштаб,
центр, вращение, разрешение, список слоёв и их состояние.
rendercomplete
Срабатывает после завершения полного рендеринга кадра:
map.on('rendercomplete', function () {
console.log('Карта полностью отрисована');
});
Используется для экспорта изображения или синхронизации внешних процессов.
moveend и movestart
Хуки перемещения карты:
map.on('movestart', () => {
console.log('Начало движения карты');
});
map.on('moveend', () => {
console.log('Окончание движения карты');
});
ol/View управляет состоянием камеры: центр, масштаб,
проекция, вращение. Все изменения доступны через события.
change:center
view.on('change:center', () => {
console.log('Изменён центр');
});
change:resolution
Срабатывает при изменении масштаба:
view.on('change:resolution', () => {
console.log('Изменён масштаб');
});
change:rotation
view.on('change:rotation', () => {
console.log('Изменение угла поворота');
});
Эти события являются низкоуровневыми хуками состояния камеры и часто используются для синхронизации UI или аналитики.
Механизм ol/interaction предоставляет поведенческие
расширения карты. Каждая интеракция также генерирует события, формируя
собственные хуки.
import Sel ect fr om 'ol/interaction/Sel ect';
const select = new Select();
select.on('select', function (e) {
console.log('Выбрано объектов:', e.selected.length);
});
Событие содержит массив выбранных и снятых объектов.
import Draw fr om 'ol/interaction/Draw';
const draw = new Draw({
type: 'Polygon'
});
draw.on('drawstart', function () {
console.log('Начало рисования');
});
draw.on('drawend', function (e) {
console.log('Завершено рисование', e.feature);
});
Хуки рисования позволяют внедрять бизнес-логику в момент создания геометрии.
import Modify fr om 'ol/interaction/Modify';
const modify = new Modify({ source: vectorSource });
modify.on('modifystart', () => {
console.log('Начало редактирования');
});
modify.on('modifyend', () => {
console.log('Конец редактирования');
});
Слои (ol/layer/Layer) также поддерживают событийную
модель.
layer.on('change:visible', () => {
console.log('Видимость слоя изменилась');
});
layer.on('change:opacity', () => {
console.log('Изменена прозрачность');
});
Источники данных (ol/source) предоставляют наиболее
важные хуки загрузки данных.
tileSource.on('tileloadstart', function (e) {
console.log('Начало загрузки тайла');
});
tileSource.on('tileloadend', function (e) {
console.log('Тайл загружен');
});
tileSource.on('tileloaderror', function (e) {
console.log('Ошибка загрузки тайла');
});
Эти события критичны для реализации прогресс-баров и контроля состояния карты.
vectorSource.on('addfeature', function (e) {
console.log('Добавлен объект', e.feature);
});
vectorSource.on('removefeature', function (e) {
console.log('Удалён объект', e.feature);
});
OpenLayers предоставляет низкоуровневые события отрисовки, которые позволяют вмешиваться в процесс визуализации.
layer.on('prerender', function (event) {
const context = event.context;
});
layer.on('postrender', function (event) {
const context = event.context;
});
Эти события предоставляют доступ к Canvas/WebGL контексту и позволяют выполнять кастомные операции отрисовки поверх стандартного пайплайна.
Во время рендеринга формируется объект frameState,
содержащий полное описание сцены:
map.on('postrender', function (event) {
const state = event.frameState;
console.log(state.viewState.center);
});
frameState используется как точка синхронизации всех
вычислений рендеринга и поведения слоёв.
Собственные расширения поведения реализуются через наследование
ol/Observable.
import BaseObject fr om 'ol/Object';
class CustomModel extends BaseObject {
setValue(val) {
this.set('value', val);
this.dispatchEvent('valuechange');
}
}
const model = new CustomModel();
model.on('valuechange', () => {
console.log('Значение изменено');
});
Этот механизм позволяет создавать архитектуру, где бизнес-логика интегрируется в событийную модель OpenLayers.
Карта может выступать как централизованный диспетчер событий всех вложенных сущностей.
map.on('singleclick', function (e) {
map.forEachFeatureAtPixel(e.pixel, function (feature) {
console.log(feature);
});
});
Этот паттерн позволяет строить «хуки клика по объектам», не привязываясь к конкретному слою.
Система хуков OpenLayers может быть представлена слоями абстракции:
Каждый уровень предоставляет собственный набор точек расширения, при
этом все они объединены общей системой Observable.
map.on('pointermove', function (event) {
const coordinate = event.coordinate;
const pixel = event.pixel;
});
Pointer-события являются фундаментом для построения пользовательских инструментов: подсветка объектов, tooltips, измерения.
Событийная модель часто используется для синхронизации нескольких источников состояния:
map.on('moveend', () => {
const center = map.getView().getCenter();
const zoom = map.getView().getZoom();
syncExternalState({ center, zoom });
});
Некоторые события позволяют влиять на поток обработки через предотвращение стандартного поведения.
map.on('singleclick', function (e) {
if (e.originalEvent.ctrlKey) {
e.preventDefault();
}
});
Хотя не все события поддерживают отмену поведения, архитектура допускает контроль логики на уровне обработчиков.
Сложные сценарии формируются через композицию нескольких событий:
moveend + rendercomplete — стабильное
обновление данныхdrawend + addfeature — валидация
геометрииtileloadend + postrender — контроль
прогресса загрузки и отрисовкиselect + change:resolution — адаптивное
поведение UIМногие хуки OpenLayers зависят от асинхронных процессов:
Это означает, что события часто приходят не в момент вызова действия, а после завершения внутренних пайплайнов обработки.
Типичный паттерн стабилизации карты:
let rendering = false;
map.on('renderstart', () => rendering = true);
map.on('rendercomplete', () => rendering = false);
Такой подход позволяет блокировать операции до завершения отрисовки.
map.dispatchEvent('custom:event');
map.on('custom:event', () => {
console.log('Пользовательское событие');
});
Пользовательские события интегрируются в общую систему без необходимости модификации ядра библиотеки.
Архитектура OpenLayers строится на единообразном механизме:
Observableevent объектыЭта модель обеспечивает гибкость, позволяя внедрять сложное поведение без изменения внутреннего кода библиотеки.