ol-cesium
Version:
OpenLayers Cesium integration library
224 lines • 17 kB
JavaScript
import { unByKey as olObservableUnByKey } from 'ol/Observable.js';
import LayerGroup from 'ol/layer/Group.js';
import { getUid } from './util';
export default class AbstractSynchronizer {
map;
view;
scene;
olLayers;
mapLayerGroup;
/**
* Map of OpenLayers layer ids (from getUid) to the Cesium ImageryLayers.
* Null value means, that we are unable to create equivalent layers.
*/
layerMap = {};
/**
* Map of listen keys for OpenLayers layer layers ids (from getUid).
*/
olLayerListenKeys = {};
/**
* Map of listen keys for OpenLayers layer groups ids (from getUid).
*/
olGroupListenKeys_ = {};
constructor(map, scene) {
this.map = map;
this.view = map.getView();
this.scene = scene;
this.olLayers = map.getLayerGroup().getLayers();
this.mapLayerGroup = map.getLayerGroup();
}
/**
* Destroy all and perform complete synchronization of the layers.
*/
synchronize() {
this.destroyAll();
this.addLayers_(this.mapLayerGroup);
}
/**
* Order counterparts using the same algorithm as the Openlayers renderer:
* z-index then original sequence order.
*/
orderLayers() {
// Ordering logics is handled in subclasses.
}
/**
* Add a layer hierarchy.
*/
addLayers_(root) {
const fifo = [{
layer: root,
parents: []
}];
while (fifo.length > 0) {
const olLayerWithParents = fifo.splice(0, 1)[0];
const olLayer = olLayerWithParents.layer;
const olLayerId = getUid(olLayer).toString();
this.olLayerListenKeys[olLayerId] = [];
console.assert(!this.layerMap[olLayerId]);
let cesiumObjects = null;
if (olLayer instanceof LayerGroup) {
this.listenForGroupChanges_(olLayer);
if (olLayer !== this.mapLayerGroup) {
cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents);
}
if (!cesiumObjects) {
olLayer.getLayers().forEach((l) => {
if (l) {
const newOlLayerWithParents = {
layer: l,
parents: olLayer === this.mapLayerGroup ?
[] :
[olLayerWithParents.layer].concat(olLayerWithParents.parents)
};
fifo.push(newOlLayerWithParents);
}
});
}
}
else {
cesiumObjects = this.createSingleLayerCounterparts(olLayerWithParents);
if (!cesiumObjects) {
// keep an eye on the layers that once failed to be added (might work when the layer is updated)
// for example when a source is set after the layer is added to the map
const layerId = olLayerId;
const layerWithParents = olLayerWithParents;
const onLayerChange = () => {
const cesiumObjs = this.createSingleLayerCounterparts(layerWithParents);
if (cesiumObjs) {
// unsubscribe event listener
layerWithParents.layer.un('change', onLayerChange);
this.addCesiumObjects_(cesiumObjs, layerId, layerWithParents.layer);
this.orderLayers();
}
};
this.olLayerListenKeys[olLayerId].push(layerWithParents.layer.on('change', onLayerChange));
}
}
// add Cesium layers
if (cesiumObjects) {
this.addCesiumObjects_(cesiumObjects, olLayerId, olLayer);
}
}
this.orderLayers();
}
/**
* Add Cesium objects.
*/
addCesiumObjects_(cesiumObjects, layerId, layer) {
this.layerMap[layerId] = cesiumObjects;
this.olLayerListenKeys[layerId].push(layer.on('change:zIndex', () => this.orderLayers()));
cesiumObjects.forEach((cesiumObject) => {
this.addCesiumObject(cesiumObject);
});
}
/**
* Remove and destroy a single layer.
* @param {ol.layer.Layer} layer
* @return {boolean} counterpart destroyed
*/
removeAndDestroySingleLayer_(layer) {
const uid = getUid(layer).toString();
const counterparts = this.layerMap[uid];
if (!!counterparts) {
counterparts.forEach((counterpart) => {
this.removeSingleCesiumObject(counterpart, false);
this.destroyCesiumObject(counterpart);
});
this.olLayerListenKeys[uid].forEach(olObservableUnByKey);
delete this.olLayerListenKeys[uid];
}
delete this.layerMap[uid];
return !!counterparts;
}
/**
* Unlisten a single layer group.
*/
unlistenSingleGroup_(group) {
if (group === this.mapLayerGroup) {
return;
}
const uid = getUid(group).toString();
const keys = this.olGroupListenKeys_[uid];
keys.forEach((key) => {
olObservableUnByKey(key);
});
delete this.olGroupListenKeys_[uid];
delete this.layerMap[uid];
}
/**
* Remove layer hierarchy.
*/
removeLayer_(root) {
if (!!root) {
const fifo = [root];
while (fifo.length > 0) {
const olLayer = fifo.splice(0, 1)[0];
const done = this.removeAndDestroySingleLayer_(olLayer);
if (olLayer instanceof LayerGroup) {
this.unlistenSingleGroup_(olLayer);
if (!done) {
// No counterpart for the group itself so removing
// each of the child layers.
olLayer.getLayers().forEach((l) => {
fifo.push(l);
});
}
}
}
}
}
/**
* Register listeners for single layer group change.
*/
listenForGroupChanges_(group) {
const uuid = getUid(group).toString();
console.assert(this.olGroupListenKeys_[uuid] === undefined);
const listenKeyArray = [];
this.olGroupListenKeys_[uuid] = listenKeyArray;
// only the keys that need to be relistened when collection changes
let contentKeys = [];
const listenAddRemove = (function () {
const collection = group.getLayers();
if (collection) {
contentKeys = [
collection.on('add', (event) => {
this.addLayers_(event.element);
}),
collection.on('remove', (event) => {
this.removeLayer_(event.element);
})
];
listenKeyArray.push(...contentKeys);
}
}).bind(this);
listenAddRemove();
listenKeyArray.push(group.on('change:layers', (e) => {
contentKeys.forEach((el) => {
const i = listenKeyArray.indexOf(el);
if (i >= 0) {
listenKeyArray.splice(i, 1);
}
olObservableUnByKey(el);
});
listenAddRemove();
}));
}
/**
* Destroys all the created Cesium objects.
*/
destroyAll() {
this.removeAllCesiumObjects(true); // destroy
let objKey;
for (objKey in this.olGroupListenKeys_) {
const keys = this.olGroupListenKeys_[objKey];
keys.forEach(olObservableUnByKey);
}
for (objKey in this.olLayerListenKeys) {
this.olLayerListenKeys[objKey].forEach(olObservableUnByKey);
}
this.olGroupListenKeys_ = {};
this.olLayerListenKeys = {};
this.layerMap = {};
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWJzdHJhY3RTeW5jaHJvbml6ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb2xjcy9BYnN0cmFjdFN5bmNocm9uaXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUMsT0FBTyxJQUFJLG1CQUFtQixFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFDaEUsT0FBTyxVQUFVLE1BQU0sbUJBQW1CLENBQUM7QUFDM0MsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLFFBQVEsQ0FBQztBQVc5QixNQUFNLENBQUMsT0FBTyxPQUFnQixvQkFBb0I7SUFDdEMsR0FBRyxDQUFNO0lBQ1QsSUFBSSxDQUFPO0lBQ1gsS0FBSyxDQUFRO0lBQ2IsUUFBUSxDQUF3QjtJQUMxQyxhQUFhLENBQWE7SUFDMUI7OztPQUdHO0lBQ08sUUFBUSxHQUE2QixFQUFFLENBQUM7SUFDbEQ7O09BRUc7SUFDTyxpQkFBaUIsR0FBcUMsRUFBRSxDQUFDO0lBQ25FOztPQUVHO0lBQ0ssa0JBQWtCLEdBQXFDLEVBQUUsQ0FBQztJQUVsRSxZQUFzQixHQUFRLEVBQUUsS0FBWTtRQUMxQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hELElBQUksQ0FBQyxhQUFhLEdBQUcsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVc7UUFDVCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJ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