package.renderer.Composite.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ol Show documentation
Show all versions of ol Show documentation
OpenLayers mapping library
The newest version!
/**
* @module ol/renderer/Composite
*/
import BaseVectorLayer from '../layer/BaseVector.js';
import MapRenderer from './Map.js';
import ObjectEventType from '../ObjectEventType.js';
import RenderEvent from '../render/Event.js';
import RenderEventType from '../render/EventType.js';
import {CLASS_UNSELECTABLE} from '../css.js';
import {checkedFonts} from '../render/canvas.js';
import {inView} from '../layer/Layer.js';
import {listen, unlistenByKey} from '../events.js';
import {replaceChildren} from '../dom.js';
/**
* @classdesc
* Canvas map renderer.
* @api
*/
class CompositeMapRenderer extends MapRenderer {
/**
* @param {import("../Map.js").default} map Map.
*/
constructor(map) {
super(map);
/**
* @private
* @type {import("../events.js").EventsKey}
*/
this.fontChangeListenerKey_ = listen(
checkedFonts,
ObjectEventType.PROPERTYCHANGE,
map.redrawText,
map,
);
/**
* @private
* @type {HTMLDivElement}
*/
this.element_ = document.createElement('div');
const style = this.element_.style;
style.position = 'absolute';
style.width = '100%';
style.height = '100%';
style.zIndex = '0';
this.element_.className = CLASS_UNSELECTABLE + ' ol-layers';
const container = map.getViewport();
container.insertBefore(this.element_, container.firstChild || null);
/**
* @private
* @type {Array}
*/
this.children_ = [];
/**
* @private
* @type {boolean}
*/
this.renderedVisible_ = true;
}
/**
* @param {import("../render/EventType.js").default} type Event type.
* @param {import("../Map.js").FrameState} frameState Frame state.
* @override
*/
dispatchRenderEvent(type, frameState) {
const map = this.getMap();
if (map.hasListener(type)) {
const event = new RenderEvent(type, undefined, frameState);
map.dispatchEvent(event);
}
}
/**
* @override
*/
disposeInternal() {
unlistenByKey(this.fontChangeListenerKey_);
this.element_.remove();
super.disposeInternal();
}
/**
* Render.
* @param {?import("../Map.js").FrameState} frameState Frame state.
* @override
*/
renderFrame(frameState) {
if (!frameState) {
if (this.renderedVisible_) {
this.element_.style.display = 'none';
this.renderedVisible_ = false;
}
return;
}
this.calculateMatrices2D(frameState);
this.dispatchRenderEvent(RenderEventType.PRECOMPOSE, frameState);
const layerStatesArray = frameState.layerStatesArray.sort(
(a, b) => a.zIndex - b.zIndex,
);
const declutter = layerStatesArray.some(
(layerState) =>
layerState.layer instanceof BaseVectorLayer &&
layerState.layer.getDeclutter(),
);
if (declutter) {
// Some layers need decluttering, turn on deferred rendering hint
frameState.declutter = {};
}
const viewState = frameState.viewState;
this.children_.length = 0;
const renderedLayerStates = [];
let previousElement = null;
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
const layerState = layerStatesArray[i];
frameState.layerIndex = i;
const layer = layerState.layer;
const sourceState = layer.getSourceState();
if (
!inView(layerState, viewState) ||
(sourceState != 'ready' && sourceState != 'undefined')
) {
layer.unrender();
continue;
}
const element = layer.render(frameState, previousElement);
if (!element) {
continue;
}
if (element !== previousElement) {
this.children_.push(element);
previousElement = element;
}
renderedLayerStates.push(layerState);
}
this.declutter(frameState, renderedLayerStates);
replaceChildren(this.element_, this.children_);
this.dispatchRenderEvent(RenderEventType.POSTCOMPOSE, frameState);
if (!this.renderedVisible_) {
this.element_.style.display = '';
this.renderedVisible_ = true;
}
this.scheduleExpireIconCache(frameState);
}
/**
* @param {import("../Map.js").FrameState} frameState Frame state.
* @param {Array} layerStates Layers.
*/
declutter(frameState, layerStates) {
if (!frameState.declutter) {
return;
}
for (let i = layerStates.length - 1; i >= 0; --i) {
const layerState = layerStates[i];
const layer = layerState.layer;
if (layer.getDeclutter()) {
layer.renderDeclutter(frameState, layerState);
}
}
layerStates.forEach((layerState) =>
layerState.layer.renderDeferred(frameState),
);
}
}
export default CompositeMapRenderer;