mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
211 lines (210 loc) • 7.9 kB
JavaScript
import { MapLibreLayer } from '@geoblocks/ol-maplibre-layer/lib';
import debounce from 'lodash.debounce';
import { unByKey } from 'ol/Observable';
import { getUrlWithParams } from '../../common/utils';
import MaplibreLayerRenderer from '../renderers/MaplibreLayerRenderer';
import defineDeprecatedProperties from '../utils/defineDeprecatedProperties';
const buildStyleUrl = (url, style, apiKey, apiKeyName) => {
return getUrlWithParams(`${url}/styles/${style}/style.json`, {
[apiKeyName]: apiKey,
}).toString();
};
export let deprecated = () => { };
if (typeof window !== 'undefined' &&
new URLSearchParams(window.location.search).get('deprecated')) {
deprecated = debounce((message) => {
console.warn(message);
}, 1000);
}
/**
* An OpenLayers layer able to display data from the [geOps Maps API](https://developer.geops.io/apis/maps).
*
* @example
* import { MaplibreLayer } from 'mobility-toolbox-js/ol';
*
* const layer = new MaplibreLayer({
* apiKey: 'yourApiKey',
* // apiKeyName: 'key',
* // mapLibreOptions: {
* // interactive: false,
* // trackResize: false,
* // attributionControl: false,
* // }
* // queryRenderedFeaturesOptions: {
* // layers: ['waters_lakes'], // map.getFeaturesAtPixel will only return lakes.
* // },
* // style: 'travic_v2',
* // url: 'https://maps.geops.io',
* });
*
* @classproperty {maplibregl.Map} mapLibreMap - The Maplibre map object. Readonly.
* @classproperty {string} style - The [geOps Maps API](https://developer.geops.io/apis/maps) style.
*
*
* @see <a href="/example/ol-maplibre-layer">OpenLayers Maplibre layer example</a>
*
* @extends {geoblocks/ol-maplibre-layer/MapLibreLayer}
* @public
*/
class MaplibreLayer extends MapLibreLayer {
set apiKey(newValue) {
this.set('apiKey', newValue);
}
get apiKey() {
return this.get('apiKey');
}
set apiKeyName(newValue) {
this.set('apiKeyName', newValue);
}
get apiKeyName() {
return this.get('apiKeyName');
}
/**
* @deprecated Use layer.mapLibreMap.
*/
get maplibreMap() {
deprecated('MaplibreLayer.maplibreMap is deprecated. Use layer.mapLibreMap.');
return this.mapLibreMap;
}
// get queryRenderedFeaturesOptions(): maplibregl.QueryRenderedFeaturesOptions {
// return this.get('queryRenderedFeaturesOptions');
// }
// set queryRenderedFeaturesOptions(
// newValue: maplibregl.QueryRenderedFeaturesOptions,
// ) {
// this.set('queryRenderedFeaturesOptions', newValue);
// }
/**
* @deprecated Use layer.mapLibreMap.
*/
get mbMap() {
deprecated('MaplibreLayer.mbMap is deprecated. Use layer.maplibreMap.');
return this.maplibreMap;
}
get style() {
return this.get('style');
}
set style(newValue) {
this.set('style', newValue);
}
get url() {
return this.get('url');
}
set url(newValue) {
this.set('url', newValue);
}
/**
* Constructor.
*
* @param {Object} options
* @param {string} options.apiKey Accesss key for [geOps APIs](https://developer.geops.io/).
* @param {string} [options.apiKeyName="key"] The [geOps Maps API](https://developer.geops.io/apis/maps) key name.
* @param {maplibregl.MapOptions} [options.mapLibreOptions={ interactive: false, trackResize: false, attributionControl: false }] MapLibre map options.
* @param {string} [options.style="travic_v2"] The [geOps Maps API](https://developer.geops.io/apis/maps) style.
* @param {string} [options.url="https://maps.geops.io"] The [geOps Maps API](https://developer.geops.io/apis/maps) url.
*/
constructor(options) {
var _a;
// Backward compatibility
if (options.mapOptions && !options.mapLibreOptions) {
deprecated('MaplibreLayer.mapOptions is deprecated. Use mapLibreOptions instead.');
options.mapLibreOptions = options.mapOptions;
}
const newOptions = Object.assign(Object.assign({ apiKeyName: 'key', style: 'travic_v2', url: 'https://maps.geops.io' }, (options || {})), { mapLibreOptions: Object.assign({}, (options.mapLibreOptions || {})) });
if (!newOptions.mapLibreOptions.style &&
((_a = newOptions.url) === null || _a === void 0 ? void 0 : _a.includes('style.json'))) {
newOptions.mapLibreOptions.style = newOptions.url;
}
else if (!newOptions.mapLibreOptions.style &&
newOptions.apiKey &&
newOptions.style &&
typeof newOptions.style === 'string') {
newOptions.mapLibreOptions.style = buildStyleUrl(newOptions.url, newOptions.style, newOptions.apiKey, newOptions.apiKeyName);
}
super(newOptions);
this.olEventsKeys = [];
// For backward compatibility with v2
defineDeprecatedProperties(this, options);
// We save the options to be able to clone the layer.
// and to see if the style is defined by the maplibreOptions given by the user.
this.set('options', options);
}
/**
* Initialize the layer and listen to feature clicks.
*/
attachToMap() {
const updateMaplibreMapDebounced = debounce(this.updateMaplibreMap.bind(this), 150);
updateMaplibreMapDebounced();
this.olEventsKeys.push(this.on('propertychange', (evt) => {
if (/(url|style|apiKey|apiKeyName)/.test(evt.key)) {
updateMaplibreMapDebounced();
}
}));
}
/**
* Create a copy of the MaplibreLayer.
*
* @param {Object} newOptions Options to override. See constructor.
* @return {MaplibreLayer} A MaplibreLayer layer
* @public
*/
clone(newOptions) {
return new MaplibreLayer(Object.assign(Object.assign({}, (this.get('options') || {})), (newOptions || {})));
}
createRenderer() {
return new MaplibreLayerRenderer(this);
}
detachFromMap() {
unByKey(this.olEventsKeys);
}
disposeInternal() {
const source = this.getSource();
super.disposeInternal();
// At this point mapLibreMap.style is undefined, so to avoid errors on layers removed after this one,
// we set the mapLibreMap to null
this.mapLibreMap = undefined;
// We don't want the source removed
this.setSource(source);
}
getStyle() {
var _a;
// If the style is a complete style object, use it directly.
if (this.style &&
typeof this.style === 'object' &&
this.style.name &&
this.style.version) {
return this.style;
}
// If the url set is already a complete style url, use it directly.
if (this.url.includes('style.json')) {
return this.url;
}
// If the user has defined the style by the maplibreOptions, we use it directly.
const opts = this.get('options');
if ((_a = opts === null || opts === void 0 ? void 0 : opts.mapLibreOptions) === null || _a === void 0 ? void 0 : _a.style) {
return opts.mapLibreOptions.style;
}
/// Otherwise build the complete style url.
return buildStyleUrl(this.url, this.style, this.apiKey, this.apiKeyName);
}
setMapInternal(map) {
if (map) {
super.setMapInternal(map);
this.attachToMap();
}
else {
this.detachFromMap();
super.setMapInternal(map);
}
}
updateMaplibreMap() {
var _a;
try {
(_a = this.mapLibreMap) === null || _a === void 0 ? void 0 : _a.setStyle(this.getStyle(), { diff: false });
}
catch (e) {
console.error('Error while updating MaplibreMap', e);
}
}
}
export default MaplibreLayer;