@terrestris/ol-util
Version:
A set of helper classes for working with openLayers
165 lines (150 loc) • 6.05 kB
text/typescript
import _isEmpty from 'lodash/isEmpty';
import _isNil from 'lodash/isNil';
import { getUid } from 'ol';
import OlCollection from 'ol/Collection';
import OlBaseLayer from 'ol/layer/Base';
import OlLayerGroup from 'ol/layer/Group';
import OlImageLayer from 'ol/layer/Image';
import OlTileLayer from 'ol/layer/Tile';
import OlMap from 'ol/Map';
import MapUtil from '../MapUtil/MapUtil';
/**
* Helper class for some operations related to permalink function.
*
* @class
*/
export class PermalinkUtil {
/**
* Creates a permalink based on the given map state. It will contain
* the current view state of the map (center and zoom) as well as
* the current (filtered) list of layers.
*
* @param {OlMap} map The OpenLayers map
* @param {string} separator The separator for the layers list and center
* coordinates in the link. Default is to ';'.
* @param {(layer: OlBaseLayer) => string} identifier Function to generate the identifier of the
* layer in the link. Default is the name
* (given by the associated property) of
* the layer.
* @param {(layer: OlBaseLayer) => boolean} filter Function to filter layers that should be
* added to the link. Default is to add all
* visible layers of type ol/layer/Tile.
* @param {string[]} customAttributes Custom layer attributes which will be saved in the permalink for each layer.
* @return {string} The permalink.
*/
static getLink = (
map: OlMap,
separator = ';',
identifier = (l: OlBaseLayer) => l?.get('name'),
filter = (l: OlBaseLayer) => !_isNil(l) &&
(l instanceof OlTileLayer || l instanceof OlImageLayer) && l.getVisible(),
customAttributes: string[] = []
): string => {
const center = map.getView().getCenter()?.join(separator) ?? '';
const zoom = map.getView().getZoom()?.toString() ?? '';
const layers = map.getAllLayers();
const visibleOnes = layers
.filter(filter)
.map(identifier)
.join(separator);
const link = new URL(window.location.href);
if (customAttributes.length > 0) {
const customLayerAttributes: Record<string, any>[] = [];
layers.forEach((layer) => {
const config: Record<string, any> = {};
customAttributes.forEach((attribute) => {
if (!_isNil(layer.get(attribute))) {
config[attribute] = layer.get(attribute);
}
});
if (!_isEmpty(config)) {
customLayerAttributes.push(config);
}
});
const customLayerAttributesString = JSON.stringify(customLayerAttributes);
link.searchParams.set('customLayerAttributes', customLayerAttributesString);
}
link.searchParams.set('center', center);
link.searchParams.set('zoom', zoom);
link.searchParams.set('layers', visibleOnes);
return link.href;
};
/**
* Applies an existing permalink to the given map.
*
* @param {OlMap} map The OpenLayers map.
* @param {string} separator The separator of the layers list and center
* coordinates in the link. Default is to ';'.
* @param {(layer: OlBaseLayer) => string} identifier Function to generate the identifier of the
* layer in the link. Default is the name
* (given by the associated property) of
* the layer.
* @param {(layer: OlBaseLayer) => boolean} filter Function to filter layers that should be
* handled by the link. Default is to consider all
* current map layers of type ol/layer/Tile.
* @return {string | null} The customLayerAttributes, if defined. Otherwise null.
*/
static applyLink = (
map: OlMap,
separator: string = ';',
identifier: (layer: OlBaseLayer) => string = l => l?.get('name'),
filter = (layer: OlBaseLayer) =>
layer instanceof OlTileLayer || layer instanceof OlImageLayer
): string | null => {
const url = new URL(window.location.href);
const center = url.searchParams.get('center');
const zoom = url.searchParams.get('zoom');
const layers = url.searchParams.get('layers');
const customLayerAttributes = url.searchParams.get('customLayerAttributes');
const allLayers = MapUtil.getAllLayers(map);
if (layers) {
const layersSplitted = layers.split(separator);
allLayers
.filter(filter)
.forEach(l => {
const visible = layersSplitted.includes(identifier(l));
l.setVisible(visible);
// also make all parent folders / groups visible so
// that the layer becomes visible in map
if (visible) {
PermalinkUtil.setParentsVisible(
map,
map.getLayerGroup().getLayers(),
getUid(l));
}
});
}
if (center) {
map.getView().setCenter([
parseFloat(center.split(separator)[0]),
parseFloat(center.split(separator)[1])
]);
}
if (zoom) {
map.getView().setZoom(parseInt(zoom, 10));
}
if (customLayerAttributes) {
return customLayerAttributes;
}
return null;
};
/**
* Search through the given Ol-Collection for the given id and
* set all parenting groups visible.
* @param {OlMap} map The openlayers map
* @param {OlCollection<OlBaseLayer>} coll The Openlayers Collection
* @param {string} id Ther layer ol uid to search for
*/
static setParentsVisible = (map: OlMap, coll: OlCollection<OlBaseLayer>, id: string) => {
coll.forEach(el => {
if (el instanceof OlLayerGroup) {
const layers = MapUtil.getLayersByGroup(map, el);
if (layers.map(layer => getUid(layer)).includes(id)) {
el.setVisible(true);
}
PermalinkUtil.setParentsVisible(map, el.getLayers(), id);
}
});
};
}
export default PermalinkUtil;