В библиотеке OpenLayers процесс отрисовки карты строится вокруг циклов рендеринга, которые запускаются при изменении состояния карты: перемещении, масштабировании, изменении слоёв или данных источников. Каждый такой цикл проходит несколько стадий, завершаясь моментом, когда итоговое изображение уже сформировано и записано в canvas или WebGL-контекст. Именно на этом этапе возникает событие postrender.
postrender — это финальная точка рендер-цикла, в которой карта уже полностью отрисована, но ещё не передана в следующий кадровый цикл браузера. Это делает событие ключевым для задач постобработки, синхронизации интерфейса и кастомной графики поверх готового кадра.
Типичный рендер-цикл OpenLayers включает следующие этапы:
frameState);На этом этапе все слои уже нарисованы, и доступен финальный результат кадра.
Событие postrender передаёт объект, содержащий информацию о текущем состоянии рендеринга:
frameState играет ключевую роль, так как позволяет точно понять, в каком состоянии находится карта в момент завершения отрисовки.
Событие привязывается непосредственно к объекту карты:
import Map from 'ol/Map.js';
map.on('postrender', function (event) {
const frameState = event.frameState;
const context = event.context;
// анализ текущего масштаба
const zoom = frameState.viewState.zoom;
// доступ к canvas-контексту
if (context) {
context.save();
context.fillStyle = 'rgba(255, 0, 0, 0.2)';
context.fillRect(0, 0, context.canvas.width, context.canvas.height);
context.restore();
}
});
В этом примере выполняется постобработка уже отрисованного кадра. Подобный подход часто используется для визуальных эффектов или отладки рендеринга.
Событие rendercomplete сигнализирует о завершении логического рендеринга всех слоёв, включая асинхронные источники (тайлы, векторные данные). В отличие от него:
Таким образом, postrender ориентирован на непрерывные эффекты, а rendercomplete — на фиксацию завершённого состояния карты.
Объект frameState содержит детализированную информацию о текущем состоянии визуализации:
viewState.center — координаты центра карты;viewState.rotation — угол поворота;viewState.resolution — текущий масштаб;size — размер viewport;time — временная метка кадра.Это позволяет синхронизировать внешние процессы с картографическим рендером.
map.on('postrender', function (event) {
const state = event.frameState.viewState;
const scale = state.resolution;
document.body.setAttribute('data-map-scale', scale);
});
Одно из наиболее распространённых применений postrender — добавление собственных графических элементов поверх уже готового изображения карты.
map.on('postrender', function (event) {
const context = event.context;
if (!context) return;
const width = context.canvas.width;
const height = context.canvas.height;
context.save();
context.strokeStyle = 'blue';
context.lineWidth = 2;
context.strokeRect(10, 10, width - 20, height - 20);
context.restore();
});
Такая техника позволяет избегать создания дополнительных слоёв и обеспечивает высокую производительность при простых визуальных эффектах.
Поскольку событие вызывается на каждом кадре рендеринга, его обработчик должен выполняться максимально быстро. Любые тяжёлые вычисления внутри postrender приводят к:
Оптимизация обычно строится вокруг следующих принципов:
postrender тесно связан с анимационным циклом карты. Каждый вызов соответствует одному отрисованному кадру, что делает его удобным для реализации плавных анимаций, синхронизированных с движением карты.
map.on('postrender', function (event) {
const elapsed = event.frameState.time;
const pulse = Math.sin(elapsed / 500);
// значение pulse может использоваться для анимации элементов
});
Такой подход обеспечивает согласованность анимации с рендерингом
карты без необходимости использования
requestAnimationFrame.
При наличии нескольких слоёв postrender вызывается после завершения компоновки всех визуальных элементов. Это позволяет:
Векторные и тайловые слои не требуют отдельной синхронизации — итоговый canvas уже содержит объединённый результат.
Событие postrender имеет ряд особенностей, влияющих на архитектуру кода:
При неправильном использовании оно становится источником деградации производительности, особенно при сложных визуализациях.
В рендер-цепочке OpenLayers можно выделить несколько связанных событий:
Совместное использование этих событий позволяет точно контролировать каждый этап визуализации карты и внедрять кастомные эффекты на разных уровнях pipeline.