Рендеринг карты в OpenLayers основан на многоуровневой системе:
Map → View → Layers → Sources → Renderers. Каждый слой
может использовать собственный механизм отрисовки (Canvas, WebGL, DOM
для overlay), а итоговый кадр собирается в рамках одного цикла
frame state.
Ключевая особенность: карта не перерисовывается «по DOM-событию» напрямую. Вместо этого используется модель запросов рендера, где изменения состояния приводят к постановке кадра в очередь.
Рендер проходит через последовательность состояний:
view (центр, zoom, resolution)layer source (тайлы, векторные данные)render eventframeStateКритический объект для анализа — frameState. Он
содержит:
Отладка начинается с проверки того, обновляется ли
frameState при ожидаемых действиях.
OpenLayers предоставляет события уровня карты:
map.on('precompose', (event) => {
console.log('precompose', event.frameState);
});
map.on('postcompose', (event) => {
console.log('postcompose', event.frameState);
});
При анализе проблем:
precompose → карта не перерисовываетсяprecompose, но нет видимого результата → проблема
в renderer или стиляхmap.getView().setCenter([0, 0]);
map.getView().setZoom(5);
Если изменения выполняются без триггера:
view.setProperties({}, true);
рендер может не запускаться.
Наиболее частая проблема — несоответствие EPSG:
EPSG:3857EPSG:4326Векторные данные могут не отображаться без трансформации:
import {transform} from 'ol/proj';
const coords = transform([lon, lat], 'EPSG:4326', 'EPSG:3857');
Если геометрия вне view.extent, слой не участвует в
отрисовке.
Отладка:
console.log(view.calculateExtent());
Tile layers зависят от загрузки сетки.
Проблемные сценарии:
Инструменты проверки:
tileLayer.getSource().on('tileloadstart', e => console.log('start', e.tile.getKey()));
tileLayer.getSource().on('tileloaderror', e => console.log('error'));
tileLayer.getSource().on('tileloadend', e => console.log('end'));
Если tileloadstart отсутствует — проблема в
resolution/grid.
Vector rendering зависит от:
style functionfeature geometry validityrender orderzIndexconst layer = new VectorLayer({
style: (feature) => {
console.log(feature.getGeometry().getType());
return defaultStyle;
}
});
Если функция не вызывается — слой не участвует в кадре.
Canvas может «молчать» при:
opacity = 0visibility = falsedisplay none у контейнераpixelRatioПроверка pixel ratio:
console.log(window.devicePixelRatio);
Принудительная диагностика:
map.renderSync();
WebGL-слои требуют отдельного анализа:
Симптом: карта есть, но слой пустой.
Проверка:
map.getLayers().forEach(l => {
console.log(l.getRenderer());
});
OpenLayers использует ленивую систему перерисовки. Для диагностики полезны:
map.render();
map.renderSync();
Разница:
render() — асинхронный кадрrenderSync() — немедленная отрисовкаТакже:
layer.changed();
source.changed();
Дополнительные точки контроля:
map.on('rendercomplete', () => {
console.log('frame done');
});
Если событие не вызывается — рендер цикл не завершён.
Слои могут «исчезать» из-за порядка отрисовки:
new TileLayer({
zIndex: 10
});
Векторный слой с меньшим zIndex может перекрываться
тайловым.
Ошибки преобразования часто выглядят как:
Контроль:
import {toLonLat, fromLonLat} from 'ol/proj';
console.log(toLonLat([x, y]));
Расширенная диагностика:
map.on('postrender', (evt) => {
const fs = evt.frameState;
console.log({
resolution: fs.viewState.resolution,
center: fs.viewState.center,
extent: fs.extent
});
});
Ключевые признаки:
resolution = undefined → view не инициализированextent → проблема projection/viewframeState → нет триггера
обновленияРазмытая карта без ошибок рендера часто связана с:
pixelRatioПроверка:
const map = new Map({
pixelRatio: window.devicePixelRatio
});
DOM overlays не участвуют в canvas render loop.
Типовые ошибки:
Диагностика:
map.on('postrender', () => {
overlay.setPosition(feature.getGeometry().getCoordinates());
});
Рендер может быть заблокирован:
changeПроверка через изоляцию слоя:
map.getLayers().clear();
При сложных проблемах рендера используется последовательная изоляция:
Каждый шаг фиксируется через precompose/postcompose и
frameState.
Анимации могут маскировать ошибки:
view.animate({
center: [0, 0],
duration: 1000
});
Если кадры не обновляются — проблема в animation queue.
Network debugging показывает:
Отсутствие запросов почти всегда указывает на upstream проблему (view/layer/source), а не на сеть.
Комбинация точек контроля:
precompose — вход в рендерpostcompose — финал слояrendercomplete — завершение кадраtileload* — источник данныхframeState — состояние сценыСовместный анализ этих сигналов позволяет локализовать сбой на уровне pipeline: от данных до пикселя.