olcs
Version:
OpenLayers Cesium integration and plugin library
234 lines • 17.1 kB
JavaScript
import { unByKey as olObservableUnByKey } from 'ol/Observable.js';
import LayerGroup from 'ol/layer/Group.js';
import { getUid } from './util.js';
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.
* @param root
*/
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.
* @param cesiumObjects
* @param layerId
* @param layer
*/
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.
* @param 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.
* @param root
*/
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.
* @param group
*/
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWJzdHJhY3RTeW5jaHJvbml6ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb2xjcy9BYnN0cmFjdFN5bmNocm9uaXplci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFHQSxPQUFPLEVBQUMsT0FBTyxJQUFJLG1CQUFtQixFQUFDLE1BQU0sa0JBQWtCLENBQUM7QUFJaEUsT0FBTyxVQUFVLE1BQU0sbUJBQW1CLENBQUM7QUFHM0MsT0FBTyxFQUFDLE1BQU0sRUFBQyxNQUFNLFdBQVcsQ0FBQztBQUVqQyxNQUFNLENBQUMsT0FBTyxPQUFnQixvQkFBb0I7SUFHdEMsR0FBRyxDQUFNO0lBQ1QsSUFBSSxDQUFPO0lBQ1gsS0FBSyxDQUFRO0lBQ2IsUUFBUSxDQUF3QjtJQUMxQyxhQUFhLENBQWE7SUFDMUI7OztPQUdHO0lBQ08sUUFBUSxHQUE2QixFQUFFLENBQUM7SUFDbEQ7O09BRUc7SUFDTyxpQkFBaUIsR0FBcUMsRUFBRSxDQUFDO0lBQ25FOztPQUVHO0lBQ0ssa0JBQWtCLEdBQXFDLEVBQUUsQ0FBQztJQUVsRSxZQUFzQixHQUFRLEVBQUUsS0FBWTtRQUMxQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsQ0FBQztRQUNmLElBQUksQ0FBQyxJQUFJLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQzFCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLElBQUksQ0FBQyxRQUFRLEdBQUcsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2hELElBQUksQ0FBQyxhQUFhLEdBQUcsR0FBRyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNILFdBQVc7UUFDVCxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7T0FHRztJ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