diff --git a/api-idee-js/src/facade/assets/css/controls/rotate.css b/api-idee-js/src/facade/assets/css/controls/rotate.css
index 1a531bf3e..c52d24b75 100644
--- a/api-idee-js/src/facade/assets/css/controls/rotate.css
+++ b/api-idee-js/src/facade/assets/css/controls/rotate.css
@@ -10,16 +10,10 @@
background-color: var(--idee-color-links) !important;
}
-.m-areas > div.m-area > div.m-panel.opened.m-rotate {
- background-color: transparent !important;
- box-shadow: none !important;
- border: none !important;
-}
-
.m-rotate-compass {
position: relative;
- width: 150px;
- height: 150px;
+ width: 90px;
+ height: 90px;
display: flex;
justify-content: center;
align-items: center;
@@ -51,15 +45,6 @@ div.m-control.m-rotate-container {
opacity: 1;
}
-.m-rotate-compass {
- position: relative;
- width: 150px;
- height: 150px;
- display: flex;
- justify-content: center;
- align-items: center;
-}
-
.m-rotate-background-exterior {
fill: var(--idee-color-primary);
}
@@ -67,43 +52,52 @@ div.m-control.m-rotate-container {
.m-rotate-background-exterior,
.m-rotate-svgPath-svg {
position: absolute;
- width: 99px;
- height: 99px;
+ /* width: 99px;
+ height: 99px; */
+ width: 80px;
+ height: 84px;
}
.m-rotate-svgPath-svg {
- width: 100px;
+ width: 85px;
}
.m-rotate-exterior-svg {
position: absolute;
- width: 120px;
- height: 120px;
+ width: 85px;
overflow: hidden;
}
+.m-rotate-exterior-svg.g-cartografia-exterior:before {
+ margin-bottom: 4px;
+}
+
+.m-rotate-exterior-svg.g-cartografia-exterior:before,
.m-rotate-exterior-svg.g-cartografia-exterior-1:before {
color: #fff;
- font-size: 100px;
+ width: inherit;
}
.m-rotate-giroscopio-svg {
position: absolute;
- width: 40px;
- height: 40px;
+ width: 26px;
+ height: 26px;
box-sizing: content-box;
+ background-color: var(--idee-color-white);
+ border-radius: 26px;
}
.m-rotate-giroscopio-svg.g-cartografia-giroscopio:before {
- font-size: 40px;
- background-color: white;
- border-radius: 40px;
+ margin: 0;
+ width: 16px;
+ margin: calc((26px - 16px) / 2);
+ border-radius: inherit;
color: var(--idee-color-primary);
}
.m-rotate-help-button {
position: absolute;
- top: 50%;
+ top: 12px;
right: 0;
transform: translateY(-50%);
background-color: var(--idee-color-primary);
@@ -111,13 +105,13 @@ div.m-control.m-rotate-container {
font-weight: bold;
border: 2px solid white;
cursor: pointer;
- width: 30px;
- height: 30px;
- border-top-right-radius: 8px;
- border-bottom-right-radius: 8px;
+ height: 19px;
+ width: 19px;
+ border-radius: 50%;
text-align: center;
font-family: 'Muli', 'sans-serif';
- font-size: 18px;
+ font-size: 10px;
+ z-index: 1;
}
#m-rotate-slider-container {
@@ -148,15 +142,16 @@ div.m-control.m-rotate-container {
}
.m-rotate-help-button:hover {
- background-color: var(--idee-color-primary);
+ background-color: var(--idee-color-links);
}
.m-rotate-rotation-maker {
position: absolute;
- width: 99px;
- height: 99px;
- fill: var(--idee-color-primary);
+ width: 88px;
+ height: 80px;
+ fill: var(--idee-color-links);
display: none;
+ overflow: hidden;
}
.m-rotate-help-container {
@@ -209,11 +204,6 @@ button.m-rotate-help-close.g-cartografia-cancelar:before {
color: #000;
}
-.m-rotate-exterior-svg.g-cartografia-exterior:before {
- color: #fff;
- font-size: 120px;
-}
-
.m-rotate-help-option {
display: flex;
gap: 8px;
diff --git a/api-idee-js/src/facade/assets/css/fonts.css b/api-idee-js/src/facade/assets/css/fonts.css
index 19e7d4149..bf974424a 100644
--- a/api-idee-js/src/facade/assets/css/fonts.css
+++ b/api-idee-js/src/facade/assets/css/fonts.css
@@ -337,5 +337,14 @@
-webkit-mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/pinterest.svg');
mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/pinterest.svg');
}
-
+
+ .g-cartografia-exterior::before {
+ -webkit-mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/rotate-exterior.svg');
+ mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/rotate-exterior.svg');
+ }
+
+ .g-cartografia-giroscopio::before {
+ -webkit-mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/rotate-giroscopio.svg');
+ mask-image: url('https://componentes.idee.es/estaticos/Simbologia/svg/icons_cota/rotate-giroscopio.svg');
+ }
}
\ No newline at end of file
diff --git a/api-idee-js/src/facade/js/Map.js b/api-idee-js/src/facade/js/Map.js
index 41b5e2369..d50eede91 100644
--- a/api-idee-js/src/facade/js/Map.js
+++ b/api-idee-js/src/facade/js/Map.js
@@ -5421,6 +5421,40 @@ class Map extends Base {
return this;
}
+ /**
+ * Este método añade una interacción de OpenLayers al mapa.
+ *
+ * @function
+ * @param {ol.interaction.Interaction} interaction Interacción a añadir.
+ * @returns {IDEE.Map} Mapa.
+ * @public
+ * @api
+ */
+ addInteraction(interaction) {
+ if (isUndefined(MapImpl.prototype.addInteraction)) {
+ Exception(getValue('exception').addinteraction_method);
+ }
+ this.getImpl().addInteraction(interaction);
+ return this;
+ }
+
+ /**
+ * Este método elimina una interacción de OpenLayers del mapa.
+ *
+ * @function
+ * @param {ol.interaction.Interaction} interaction Interacción a eliminar.
+ * @returns {IDEE.Map} Mapa.
+ * @public
+ * @api
+ */
+ removeInteraction(interaction) {
+ if (isUndefined(MapImpl.prototype.removeInteraction)) {
+ Exception(getValue('exception').removeinteraction_method);
+ }
+ this.getImpl().removeInteraction(interaction);
+ return this;
+ }
+
/**
* Este método permite activar o desactivar la interacción de panneo.
* El valor por defecto es true.
diff --git a/api-idee-js/src/facade/js/control/Location.js b/api-idee-js/src/facade/js/control/Location.js
index 8d20c893b..575fb27b4 100644
--- a/api-idee-js/src/facade/js/control/Location.js
+++ b/api-idee-js/src/facade/js/control/Location.js
@@ -5,6 +5,7 @@ import LocationImpl from 'impl/control/Location';
import locationTemplate from 'templates/location';
import myhelp from 'templates/locationhelp';
import 'assets/css/controls/location';
+import * as EventType from 'IDEE/event/eventtype';
import { getValue } from '../i18n/language';
import ControlBase from './Control';
import {
@@ -68,7 +69,11 @@ class Location extends ControlBase {
}
// implementation of this control
- const impl = new LocationImpl(tracking, highAccuracy, 60000, vendorOptions);
+ const impl = new LocationImpl({
+ tracking,
+ highAccuracy,
+ vendorOptions,
+ });
// calls the super constructor
super(Location.NAME, impl, options);
@@ -101,9 +106,10 @@ class Location extends ControlBase {
* @api
*/
createView(map) {
+ const lang = this.translation || {};
const element = compileTemplate(locationTemplate, {
vars: {
- title: this.tooltip ?? getValue('location').title,
+ title: this.tooltip ?? lang.title,
},
});
@@ -131,6 +137,60 @@ class Location extends ControlBase {
return element.querySelector('button#m-location-button');
}
+ /**
+ * Genera un objeto clave-valor traducido con los datos actualizados.
+ * Perfecto para el InfoBox nativo de Cesium.
+ * @param {number} lon
+ * @param {number} lat
+ * @returns {Object} Diccionario mapeado con traducciones vigentes
+ */
+ getPopupProperties(lon, lat) {
+ const lang = this.translation || {};
+ const labels = lang.popup;
+
+ return {
+ [labels.title]: labels.titleValue || 'Mi ubicación',
+ [labels.longitude]: typeof lon === 'number' ? lon.toFixed(6) : lon,
+ [labels.latitude]: typeof lat === 'number' ? lat.toFixed(6) : lat,
+ };
+ }
+
+ /**
+ * Crea un contenedor DOM con una tabla estructurada y traducida.
+ * Perfecto para inyectar en Overlays de OpenLayers.
+ * @param {number} lon
+ * @param {number} lat
+ * @returns {HTMLElement} Elemento contenedor de la tabla
+ */
+ createPopupContent(lon, lat) {
+ const lang = this.translation || {};
+ const labels = lang.popup;
+
+ const container = document.createElement('div');
+ container.className = 'm-location-popup-container';
+
+ container.innerHTML = `
+
+ `;
+ return container;
+ }
+
/**
* Obtiene la ayuda del control
*
@@ -139,7 +199,8 @@ class Location extends ControlBase {
* @api
*/
getHelp() {
- const textHelp = getValue('location').textHelp;
+ const lang = this.translation || {};
+ const textHelp = lang.textHelp;
return {
title: Location.NAME,
content: new Promise((success) => {
@@ -147,9 +208,9 @@ class Location extends ControlBase {
vars: {
urlImages: `${IDEE.config.STATIC_RESOURCES_URL}/imagenes/controles`,
translations: {
- help1: textHelp.text1,
- help2: textHelp.text2,
- help3: textHelp.text2,
+ help1: textHelp.text1 ?? '',
+ help2: textHelp.text2 ?? '',
+ help3: textHelp.text2 ?? '',
},
},
});
@@ -183,6 +244,15 @@ class Location extends ControlBase {
setTracking(tracking) {
this.getImpl().tracking = tracking;
}
+
+ /**
+ * @override
+ * Destroys facade implementacion of this control
+ */
+ destroy() {
+ super.destroy();
+ this.un(EventType.CHANGE);
+ }
}
/**
diff --git a/api-idee-js/src/facade/js/i18n/en.json b/api-idee-js/src/facade/js/i18n/en.json
index a124e63e1..bd137cf0b 100644
--- a/api-idee-js/src/facade/js/i18n/en.json
+++ b/api-idee-js/src/facade/js/i18n/en.json
@@ -20,6 +20,12 @@
},
"location": {
"title": "Get current location",
+ "popup": {
+ "title": "Location",
+ "titleValue": "Current Position",
+ "longitude": "Longitude",
+ "latitude": "Latitude"
+ },
"textHelp": {
"text1": "The location tool allows you to obtain the position of a device and position it on the map. Its operation is restricted to WEB pages that are published securely over the HTTPS protocol and in local environments.",
"text2": "If used on a mobile device equipped with a GNSS system, the position will be obtained according to the device's location permissions.",
@@ -262,6 +268,8 @@
"invalidBase64Encoding": "Invalid base64 encoding",
"invalidJsonFormat": "Invalid JSON format",
"removecontrol_method": "The used implementation does not have the removeControls method.",
+ "addinteraction_method": "La implementación usada no posee el método addInteraction.",
+ "removeinteraction_method": "La implementación usada no posee el método removeInteraction.",
"setmaxextent_method": "The used implementation does not have the setMaxExtent method.",
"flyTo_method": "The used implementation does not have the flyTo method.",
"getbbox_method": "The used implementation does not have the getBbox method.",
diff --git a/api-idee-js/src/facade/js/i18n/es.json b/api-idee-js/src/facade/js/i18n/es.json
index e40106273..c1cc5d8c1 100644
--- a/api-idee-js/src/facade/js/i18n/es.json
+++ b/api-idee-js/src/facade/js/i18n/es.json
@@ -21,6 +21,12 @@
"location": {
"error": "El control ubicación no acepta http. Debe usar https.",
"title": "Obtener ubicación actual",
+ "popup": {
+ "title": "Ubicación",
+ "titleValue": "Posición actual",
+ "longitude": "Longitud",
+ "latitude": "Latitud"
+ },
"textHelp": {
"text1": "La herramienta de localización permite obtener la posición de un dispositivo y posicionarla en el mapa. Su funcionamiento queda restringido a páginas WEB que se publiquen de forma segura sobre el protocolo HTTPS y en entornos locales.",
"text2": "En el caso de su utilización en un dispositivo móvil provisto de un sistema GNSS, se obtendrá la posición según los permisos de localización del dispositivo.",
@@ -263,6 +269,8 @@
"invalidBase64Encoding": "Codificación base64 inválida",
"invalidJsonFormat": "Formato JSON inválido",
"removecontrol_method": "La implementación usada no posee el método removeControls.",
+ "addinteraction_method": "The used implementation does not have the addInteraction method.",
+ "removeinteraction_method": "The used implementation does not have the removeInteraction method.",
"setmaxextent_method": "La implementación usada no posee el método setMaxExtent.",
"flyTo_method": "La implementación usada no posee el método flyTo.",
"getbbox_method": "La implementación usada no posee el método getBbox.",
diff --git a/api-idee-js/src/facade/js/ui/panels/Panel.js b/api-idee-js/src/facade/js/ui/panels/Panel.js
index 1b859a6ca..aec93595d 100644
--- a/api-idee-js/src/facade/js/ui/panels/Panel.js
+++ b/api-idee-js/src/facade/js/ui/panels/Panel.js
@@ -334,14 +334,13 @@ class Panel extends MObject {
/**
* Este método elimina los controles del panel.
* - ⚠️ Advertencia: Este método no debe ser llamado por el usuario.
- * @public
+ * @private
* @function
* @param {array} controls Control.
* @api
*/
_removeControl(controlsParam) {
- const controls = this.map.controls(controlsParam);
- controls.forEach((control) => {
+ this.map.controls(controlsParam).forEach((control) => {
const index = this.controls.indexOf(control);
if (index !== -1) {
this.controls.splice(index, 1);
diff --git a/api-idee-js/src/facade/js/util/LoadFiles.js b/api-idee-js/src/facade/js/util/LoadFiles.js
index 248147631..f8ad5b35d 100644
--- a/api-idee-js/src/facade/js/util/LoadFiles.js
+++ b/api-idee-js/src/facade/js/util/LoadFiles.js
@@ -28,6 +28,32 @@ export const loadFeaturesLoadFilesImpl = (map, layerName, features) => {
const layer = new Vector({ name: layerName, legend: layerName, extract: true });
layer.addFeatures(features);
map.addLayers(layer);
+ features.forEach((feature) => {
+ let labelText = feature.getAttribute('lbl_txt');
+ let labelFont = feature.getAttribute('lbl_font');
+ let labelColor = feature.getAttribute('lbl_clr');
+ if (!labelText) {
+ const desc = feature.getAttribute('desc');
+ if (desc && desc.includes('lbl_txt=')) {
+ desc.split('\n').forEach((pair) => {
+ const sep = pair.indexOf('=');
+ if (sep > 0) {
+ const key = pair.substring(0, sep);
+ const val = pair.substring(sep + 1);
+ if (key === 'lbl_txt') labelText = val;
+ else if (key === 'lbl_font') labelFont = val;
+ else if (key === 'lbl_clr') labelColor = val;
+ }
+ });
+ }
+ }
+ if (labelText) {
+ feature.setStyle(new IDEE.style.Point({
+ radius: 0,
+ label: { text: labelText, font: labelFont, color: labelColor },
+ }));
+ }
+ });
LoadFilesImpl.centerFeatures(features, map);
}
};
diff --git a/api-idee-js/src/impl/cesium/js/Map.js b/api-idee-js/src/impl/cesium/js/Map.js
index 42a77fc49..fb34120c1 100755
--- a/api-idee-js/src/impl/cesium/js/Map.js
+++ b/api-idee-js/src/impl/cesium/js/Map.js
@@ -140,6 +140,13 @@ class Map extends MObject {
*/
this.controls_ = [];
+ /**
+ * Interacciones añadidas al mapa.
+ * @private
+ * @type {Array}
+ */
+ this.interactions_ = [];
+
/**
* Indica si el zoom inicial fue calculado. Por defecto verdadero.
* @private
@@ -2460,6 +2467,18 @@ class Map extends MObject {
};
}
+ /**
+ * Obtiene la proyección nativa de Cesium activa en el mapa.
+ *
+ * @function
+ * @returns {GeographicProjection} Instancia nativa de Cesium MapProjection.
+ * @public
+ * @api
+ */
+ getNativeProjection() {
+ return this.map_.scene.mapProjection;
+ }
+
/**
* Este método obtiene la implementación del mapa.
*
@@ -2739,6 +2758,45 @@ class Map extends MObject {
});
}
+ /**
+ * Este método añade una interacción al mapa.
+ *
+ * @function
+ * @param {Object} interaction Interacción a añadir.
+ * @returns {Map} Mapa.
+ * @public
+ * @api
+ */
+ addInteraction(interaction) {
+ if (!isNullOrEmpty(interaction) && !this.interactions_.includes(interaction)) {
+ this.interactions_.push(interaction);
+ if (typeof interaction.activate === 'function') {
+ interaction.activate(this.map_);
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Este método elimina una interacción del mapa.
+ *
+ * @function
+ * @param {Object} interaction Interacción a eliminar.
+ * @returns {Map} Mapa.
+ * @public
+ * @api
+ */
+ removeInteraction(interaction) {
+ const idx = this.interactions_.indexOf(interaction);
+ if (idx !== -1) {
+ if (typeof interaction.deactivate === 'function') {
+ interaction.deactivate();
+ }
+ this.interactions_.splice(idx, 1);
+ }
+ return this;
+ }
+
/**
* Función que obtiene el nombre de la implementación del mapa.
*
diff --git a/api-idee-js/src/impl/cesium/js/control/Location.js b/api-idee-js/src/impl/cesium/js/control/Location.js
index 736923f64..6692e011e 100644
--- a/api-idee-js/src/impl/cesium/js/control/Location.js
+++ b/api-idee-js/src/impl/cesium/js/control/Location.js
@@ -8,6 +8,17 @@ import * as Cesium from 'cesium';
import Control from './Control';
import Feature from '../feature/Feature';
+/**
+ * @typedef {Object} Options Opciones de configuración del control de implementación
+ * @param {Boolean} [tracking] Seguimiento de la localización, por defecto verdadero.
+ * @param {Boolean} [highAccuracy] Alta precisión del seguimiento, por defecto falso.
+ * @param {Number} [maximumAge] Indica la antigüedad máxima en milisegundos de una posible
+ * posición almacenada en caché.
+ * Valor por defecto 60000.
+ * @param {Object} [vendorOptions] Opciones de proveedor para la biblioteca base,
+ * por defecto objeto vacío. Estos valores no son configurables.
+*/
+
/**
* @classdesc
* Hereda de {@link module:IDEE/impl/control/Control|Control}.
@@ -25,24 +36,22 @@ import Feature from '../feature/Feature';
class Location extends Control {
/**
* @constructor
- * @param {Boolean} tracking Seguimiento de la localización.
- * @param {Boolean} highAccuracy Alta precisión del seguimiento.
- * @param {Number} maximumAge Antigüedad máxima en caché.
- * @param {Object} vendorOptions Opciones de proveedor para Cesium/Geolocation.
+ * @extends {IDEE.impl.Control}
+ * @param {Options} options
* @example
* const control = new IDEE.impl.ol.control.Location(true, false, 60000, {
* enableHighAccuracy: true,
* });
*/
- constructor(tracking, highAccuracy, maximumAge, vendorOptions) {
- super(vendorOptions);
+ constructor(options = {}) {
+ super(options.vendorOptions);
/**
* Opciones para la biblioteca base.
* @private
* @type {Object}
*/
- this.vendorOptions_ = vendorOptions;
+ this.vendorOptions_ = options.vendorOptions;
this.watchId_ = null;
/**
@@ -50,21 +59,21 @@ class Location extends Control {
* @private
* @type {Boolean}
*/
- this.tracking_ = tracking;
+ this.tracking_ = options.tracking ?? true;
/**
* Alta precisión del seguimiento, por defecto falso.
* @private
* @type {Boolean}
*/
- this.highAccuracy_ = highAccuracy;
+ this.highAccuracy_ = options.highAccuracy ?? false;
/**
* Valor por defecto 60000.
* @private
* @type {Number}
*/
- this.maximumAge_ = maximumAge;
+ this.maximumAge_ = options.maximumAge ?? 6000;
/**
* Activa el control.
@@ -101,7 +110,7 @@ class Location extends Control {
outlineWidth: 1,
},
});
- // Inyección de compatibilidad (Duck Typing) para la fachada Feature.js
+
cesiumAccuracyEntity.get = (key) => {
return this[key];
};
@@ -121,8 +130,20 @@ class Location extends Control {
disableDepthTestDistance: Number.POSITIVE_INFINITY,
},
});
- // Inyección de compatibilidad (Duck Typing) para la fachada Feature.js
+
+ cesiumPositionEntity.getAttributes = () => {
+ return this._rawProperties;
+ };
+
+ cesiumPositionEntity.getAttribute = (key) => {
+ return this._rawProperties[key];
+ };
+
cesiumPositionEntity.get = (key) => {
+ // eslint-disable-next-line no-prototype-builtins
+ if (this._rawProperties && this._rawProperties.hasOwnProperty(key)) {
+ return this._rawProperties[key];
+ }
return this[key];
};
cesiumPositionEntity.isUtilityFeature = true;
@@ -150,10 +171,9 @@ class Location extends Control {
const accuracy = position.coords.accuracy;
const newCoord = [lon, lat];
- // Cesium trabaja con coordenadas Cartesianas 3D basándose en WGS84 (grados)
const centerCartesian = Cesium.Cartesian3.fromDegrees(lon, lat);
- // 1. Actualizar posición y radio de la geometría de precisión
+ // Actualizar anillo de precisión
const accEntity = this.accuracyFeature_.getImpl().getFeature();
accEntity.position = centerCartesian;
if (accEntity.ellipse) {
@@ -161,11 +181,18 @@ class Location extends Control {
accEntity.ellipse.semiMinorAxis = accuracy;
}
- // 2. Actualizar posición del punto indicador
const posEntity = this.positionFeature_.getImpl().getFeature();
posEntity.position = centerCartesian;
- // 3. Reposicionar el mapa global (Fachada)
+ if (!isNullOrEmpty(this.facadeObj_)) {
+ const translatedProps = this.facadeObj_.getPopupProperties(lon, lat);
+
+ posEntity.properties = new Cesium.PropertyBag(translatedProps);
+
+ // eslint-disable-next-line no-underscore-dangle
+ posEntity._rawProperties = translatedProps;
+ }
+
this.facadeMap_.setCenter(newCoord);
if (this.element.classList.contains('m-locating')) {
this.facadeMap_.setZoom(Location.ZOOM);
@@ -174,12 +201,10 @@ class Location extends Control {
this.element.classList.remove('m-locating');
this.element.classList.add('m-located');
- // Si no requiere trackear continuamente, apagamos el watcher tras la primera lectura fija
if (!this.tracking_) {
this.clearWatch_();
}
- // 4. Notificar cambios a la fachada mediante eventos abstractos
if (!isNullOrEmpty(this.facadeObj_)) {
if (!setEquals(newCoord, this.lastCoord_)) {
this.facadeObj_.fire(EventType.CHANGE, [newCoord]);
diff --git a/api-idee-js/src/impl/ol/js/Map.js b/api-idee-js/src/impl/ol/js/Map.js
index c2ddc9896..9e6659412 100644
--- a/api-idee-js/src/impl/ol/js/Map.js
+++ b/api-idee-js/src/impl/ol/js/Map.js
@@ -3889,6 +3889,34 @@ class Map extends MObject {
this.getMapImpl().getView().setResolution(resolution);
}
+ /**
+ * Este método añade una interacción de OpenLayers al mapa.
+ *
+ * @function
+ * @param {ol.interaction.Interaction} interaction Interacción a añadir.
+ * @returns {Map} Mapa.
+ * @public
+ * @api
+ */
+ addInteraction(interaction) {
+ this.map_.addInteraction(interaction);
+ return this;
+ }
+
+ /**
+ * Este método elimina una interacción de OpenLayers del mapa.
+ *
+ * @function
+ * @param {ol.interaction.Interaction} interaction Interacción a eliminar.
+ * @returns {Map} Mapa.
+ * @public
+ * @api
+ */
+ removeInteraction(interaction) {
+ this.map_.removeInteraction(interaction);
+ return this;
+ }
+
/**
* Función que obtiene el nombre de la implementación del mapa.
*
diff --git a/api-idee-js/src/impl/ol/js/control/Attributions.js b/api-idee-js/src/impl/ol/js/control/Attributions.js
index 3617f68ca..40633809f 100644
--- a/api-idee-js/src/impl/ol/js/control/Attributions.js
+++ b/api-idee-js/src/impl/ol/js/control/Attributions.js
@@ -27,7 +27,7 @@ class Attributions extends Control {
* @api stable
*/
constructor(options = {}) {
- super();
+ super(options);
/**
* Map of the plugin
* @private
diff --git a/api-idee-js/src/impl/ol/js/control/Location.js b/api-idee-js/src/impl/ol/js/control/Location.js
index 14260db24..162e8cb68 100644
--- a/api-idee-js/src/impl/ol/js/control/Location.js
+++ b/api-idee-js/src/impl/ol/js/control/Location.js
@@ -1,3 +1,4 @@
+/* eslint-disable no-underscore-dangle */
/**
* @module IDEE/impl/control/Location
*/
@@ -17,6 +18,17 @@ import OLStyleStroke from 'ol/style/Stroke';
import Control from './Control';
import Feature from '../feature/Feature';
+/**
+ * @typedef {Object} Options Opciones de configuración del control de implementación
+ * @param {Boolean} [tracking] Seguimiento de la localización, por defecto verdadero.
+ * @param {Boolean} [highAccuracy] Alta precisión del seguimiento, por defecto falso.
+ * @param {Number} [maximumAge] Indica la antigüedad máxima en milisegundos de una posible
+ * posición almacenada en caché.
+ * Valor por defecto 60000.
+ * @param {Object} [vendorOptions] Opciones de proveedor para la biblioteca base,
+ * por defecto objeto vacío. Estos valores no son configurables.
+*/
+
/**
* @classdesc
* Hereda de {@link module:IDEE/impl/control/Control|Control}.
@@ -41,30 +53,23 @@ class Location extends Control {
* posición en el mapa.
*
* @constructor
- * @param {Boolean} tracking Seguimiento de la localización, por defecto verdadero.
- * @param {Boolean} highAccuracy Alta precisión del seguimiento, por defecto falso.
- * @param {Number} maximumAge Indica la antigüedad máxima en milisegundos de una posible
- * posición almacenada en caché.
- * Valor por defecto 60000.
- * @param {Object} vendorOptions Opciones de proveedor para la biblioteca base,
- * por defecto objeto vacío. Estos valores no son configurables.
+ * @extends {IDEE.impl.Control}
+ * @param {Options} options
* @example
* const control = new IDEE.impl.ol.control.Location(true, false, 60000, {
* enableHighAccuracy: true,
* });
- * @extends {IDEE.impl.Control}
* @api stable
*/
-
- constructor(tracking, highAccuracy, maximumAge, vendorOptions) {
- super(vendorOptions);
+ constructor(options = {}) {
+ super(options.vendorOptions);
/**
* Opciones para la biblioteca base.
* @private
* @type {Object}
*/
- this.vendorOptions_ = vendorOptions;
+ this.vendorOptions_ = options.vendorOptions;
/**
* Proporcionar Geolocalización HTML5.
@@ -79,7 +84,7 @@ class Location extends Control {
* @type {OLFeature}
*/
const olAccuracyFeature = new OLFeature();
- olAccuracyFeature.set('isUtilityFeature', true); // No interactivo
+ olAccuracyFeature.set('isUtilityFeature', true);
this.accuracyFeature_ = Feature.feature2Facade(olAccuracyFeature);
/**
@@ -87,21 +92,21 @@ class Location extends Control {
* @private
* @type {Boolean}
*/
- this.tracking_ = tracking;
+ this.tracking_ = options.tracking ?? true;
/**
* Alta precisión del seguimiento, por defecto falso.
* @private
* @type {Boolean}
*/
- this.highAccuracy_ = highAccuracy;
+ this.highAccuracy_ = options.highAccuracy ?? false;
/**
* Valor por defecto 60000.
* @private
* @type {Number}
*/
- this.maximumAge_ = maximumAge;
+ this.maximumAge_ = options.maximumAge ?? 6000;
/**
* Activa el control.
@@ -168,18 +173,28 @@ class Location extends Control {
},
}, this.vendorOptions_, true));
this.geolocation_.on('change:accuracyGeometry', (evt) => {
- const accuracyGeom = evt.target.get(evt.key);
+ // const accuracyGeom = evt.target.get(evt.key);
+ const accuracyGeom = evt.target.getAccuracyGeometry();
+ if (accuracyGeom) {
+ const nativeMap = this.facadeMap_.getImpl().map_;
+ const mapProjection = nativeMap.getView().getProjection();
+ accuracyGeom.transform('EPSG:4326', mapProjection);
+ const nativeAccuracyFeature = this.accuracyFeature_.getImpl().getFeature();
+ nativeAccuracyFeature.setGeometry(accuracyGeom);
+ nativeAccuracyFeature.setStyle(Location.ACCURACY_STYLE);
+ }
this.accuracyFeature_.getImpl().getFeature().setGeometry(accuracyGeom);
});
this.geolocation_.on('change:position', (evt) => {
- const newCoord = evt.target.get(evt.key);
+ const [lon, lat] = evt.target.get(evt.key);
+ const newCoord = [lon, lat];
const newPosition = isNullOrEmpty(newCoord)
? null
: new OLGeomPoint(newCoord);
this.positionFeature_.getImpl().getFeature().setGeometry(newPosition);
this.facadeMap_.setCenter(newCoord);
if (this.element.classList.contains('m-locating')) {
- this.facadeMap_.setZoom(Location.ZOOM); // solo 1a vez
+ this.facadeMap_.setZoom(Location.ZOOM);
}
this.element.classList.remove('m-locating');
this.element.classList.add('m-located');
@@ -283,6 +298,24 @@ Location.POSITION_STYLE = new OLStyle({
}),
});
+/**
+ * Estilo del area de cercanía para la localización.
+ * @const
+ * @type {ol.style.Style}
+ * @public
+ * @api stable
+ * @memberof module:IDEE/impl/control/Location~
+ */
+Location.ACCURACY_STYLE = new OLStyle({
+ fill: new OLStyleFill({
+ color: 'rgba(0, 204, 255, 0.12)',
+ }),
+ stroke: new OLStyleStroke({
+ color: 'rgba(0, 68, 85, 0.42)',
+ width: 1.5,
+ }),
+});
+
/**
* Zoom de la localización.
* @const
diff --git a/api-idee-js/src/impl/ol/js/projections.js b/api-idee-js/src/impl/ol/js/projections.js
index 6c16ff9b4..e3c3f9175 100644
--- a/api-idee-js/src/impl/ol/js/projections.js
+++ b/api-idee-js/src/impl/ol/js/projections.js
@@ -5,7 +5,7 @@
import proj4 from 'proj4';
import OLProjection from 'ol/proj/Projection';
import { register } from 'ol/proj/proj4';
-import { addEquivalentProjections } from 'ol/proj';
+import { addEquivalentProjections, get as getProj } from 'ol/proj';
import { parseCRSWKTtoJSON } from '../../../facade/js/util/Utils';
/**
@@ -709,6 +709,25 @@ const setNewProjection = async (projection) => {
addProjections([newProjection]);
};
+/**
+ * Asegura que una proyección está registrada. Si no lo está, la obtiene de epsg.io y la registra.
+ * @param {String} projCode Código EPSG de la proyección
+ * @returns {Promise} true si la proyección está disponible, false si no existe
+ * @public
+ * @function
+ * @api
+ */
+const ensureProjection = async (projCode) => {
+ const normalizedCode = projCode.startsWith('EPSG:') ? projCode : `EPSG:${projCode}`;
+ if (getProj(normalizedCode)) return true;
+ try {
+ await setNewProjection(normalizedCode);
+ return true;
+ } catch {
+ return false;
+ }
+};
+
// register proj4
addProjections(projections, false);
@@ -724,4 +743,5 @@ export default {
addProjections,
getSupportedProjs,
setNewProjection,
+ ensureProjection,
};
diff --git a/api-idee-js/src/plugins/infocoordinates/src/facade/js/infocoordinatescontrol.js b/api-idee-js/src/plugins/infocoordinates/src/facade/js/infocoordinatescontrol.js
index f9e1e41e0..9bef06eb7 100644
--- a/api-idee-js/src/plugins/infocoordinates/src/facade/js/infocoordinatescontrol.js
+++ b/api-idee-js/src/plugins/infocoordinates/src/facade/js/infocoordinatescontrol.js
@@ -156,6 +156,7 @@ export default class InfocoordinatesControl extends IDEE.Control {
const openDropdown = () => {
if (!isEditable) {
+ this.refreshProjectionsSelector(selector);
selector.classList.remove('noDisplay');
arrow.classList.add('arrow-up');
}
@@ -194,6 +195,9 @@ export default class InfocoordinatesControl extends IDEE.Control {
});
arrow.addEventListener('click', () => {
+ if (selector.classList.contains('noDisplay')) {
+ this.refreshProjectionsSelector(selector);
+ }
selector.classList.toggle('noDisplay');
arrow.classList.toggle('arrow-up');
});
@@ -491,6 +495,32 @@ export default class InfocoordinatesControl extends IDEE.Control {
idBotonTab.classList.add('active');
}
+ /**
+ * Refresca el listado de proyecciones del selector de EPSG con las
+ * proyecciones actualmente soportadas, incluyendo las registradas
+ * al vuelo por otros plugins.
+ * @param {HTMLElement} selector Elemento del selector de EPSG
+ * @public
+ * @function
+ * @api
+ */
+ refreshProjectionsSelector(selector) {
+ this.projections = IDEE.impl.ol.js.projections.getSupportedProjs();
+ // eslint-disable-next-line no-param-reassign
+ selector.innerHTML = `
+ -
+ ${getValue('choose_create_epsg')}
+
+ ${this.projections.map((proj) => `
+ -
+
+ ${proj.codes[0]}
+
+
+ `).join('')}
+ `;
+ }
+
changeSelectSRSorChangeFormat() {
// Cojo la tab activa
const elem = document.querySelector('.tablinks.active');
@@ -520,38 +550,18 @@ export default class InfocoordinatesControl extends IDEE.Control {
const formatGMS = document.getElementById('m-infocoordinates-buttonConversorFormat').checked;
// Cambio coordenadas y calculo las UTM
- let pointDataOutput;
- try {
- pointDataOutput = this.getImpl().getCoordinates(
- featureSelected,
- selectSRS,
- formatGMS,
- this.decimalGEOcoord_,
- this.decimalUTMcoord_,
- );
+ if (!await IDEE.impl.ol.js.projections.ensureProjection(selectSRS)) {
+ IDEE.dialog.error(`${getValue('exception.srs')} ${this.selectedProjection}`);
+ } else {
this.selectedProjection = selectSRS;
- } catch (error) {
- try {
- await IDEE.impl.ol.js.projections.setNewProjection(selectSRS);
- pointDataOutput = this.getImpl().getCoordinates(
- featureSelected,
- selectSRS,
- formatGMS,
- this.decimalGEOcoord_,
- this.decimalUTMcoord_,
- );
- this.selectedProjection = selectSRS;
- } catch (err) {
- pointDataOutput = this.getImpl().getCoordinates(
- featureSelected,
- this.selectedProjection,
- formatGMS,
- this.decimalGEOcoord_,
- this.decimalUTMcoord_,
- );
- IDEE.dialog.error(`${getValue('exception.srs')} ${this.selectedProjection}`);
- }
}
+ const pointDataOutput = this.getImpl().getCoordinates(
+ featureSelected,
+ this.selectedProjection,
+ formatGMS,
+ this.decimalGEOcoord_,
+ this.decimalUTMcoord_,
+ );
inputSRS.value = this.selectedProjection;
this.isProjGeographic = this.getImpl().isProjGeographic(this.selectedProjection);
const gmsButton = document.getElementById('m-infocoordinates-buttonConversorFormat');
@@ -565,19 +575,7 @@ export default class InfocoordinatesControl extends IDEE.Control {
gmsButton.checked = false;
gmsButton.setAttribute('disabled', 'disabled');
}
- this.projections = IDEE.impl.ol.js.projections.getSupportedProjs();
- selector.innerHTML = `
- -
- ${getValue('choose_create_epsg')}
-
- ${this.projections.map((proj) => `
- -
-
- ${proj.codes[0]}
-
-
- `).join('')}
- `;
+ this.refreshProjectionsSelector(selector);
// pinto
pointBox.innerHTML = pointDataOutput.NumPoint;
diff --git a/api-idee-js/src/plugins/mousesrs/src/impl/ol/js/mousesrscontrol.js b/api-idee-js/src/plugins/mousesrs/src/impl/ol/js/mousesrscontrol.js
index 1bf9adace..9c104ce53 100644
--- a/api-idee-js/src/plugins/mousesrs/src/impl/ol/js/mousesrscontrol.js
+++ b/api-idee-js/src/plugins/mousesrs/src/impl/ol/js/mousesrscontrol.js
@@ -303,24 +303,15 @@ export default class MouseSRSControl extends IDEE.impl.Control {
*/
async getDecimalUnits() {
let decimalDigits;
- let srsUnits;
- try {
- // eslint-disable-next-line no-underscore-dangle
- srsUnits = ol.proj.get(this.srs).units_;
- } catch (e) {
- try {
- await IDEE.impl.ol.js.projections.setNewProjection(this.srs);
- const newProj = ol.proj.get(this.srs);
- // eslint-disable-next-line no-underscore-dangle
- srsUnits = newProj.units_;
- } catch (err) {
+ if (!ol.proj.get(this.srs)) {
+ if (!await IDEE.impl.ol.js.projections.ensureProjection(this.srs)) {
this.srs = 'EPSG:4326';
this.label = this.formatEPSG(this.srs);
IDEE.dialog.error(`${getValue('exception.srs')} ${this.srs}`);
- // eslint-disable-next-line no-underscore-dangle
- srsUnits = ol.proj.get('EPSG:4326').units_;
}
}
+ // eslint-disable-next-line no-underscore-dangle
+ const srsUnits = ol.proj.get(this.srs).units_;
if (srsUnits === 'd' && this.geoDecimalDigits !== undefined) {
decimalDigits = this.geoDecimalDigits;
diff --git a/api-idee-js/src/plugins/printviewmanagement/src/facade/js/templateCustomizer.js b/api-idee-js/src/plugins/printviewmanagement/src/facade/js/templateCustomizer.js
index 80daf14d1..4786fde49 100644
--- a/api-idee-js/src/plugins/printviewmanagement/src/facade/js/templateCustomizer.js
+++ b/api-idee-js/src/plugins/printviewmanagement/src/facade/js/templateCustomizer.js
@@ -791,6 +791,32 @@ export default class TemplateCustomizer extends IDEE.Control {
});
}
+ /**
+ * Refresca el listado de proyecciones del selector de EPSG con las
+ * proyecciones actualmente soportadas, incluyendo las registradas
+ * al vuelo por otros plugins.
+ * @param {HTMLElement} selectorEl Elemento del selector de EPSG
+ * @public
+ * @function
+ * @api
+ */
+ refreshProjectionsSelector(selectorEl) {
+ this.projectionsOptions_ = IDEE.impl.ol.js.projections.getSupportedProjs();
+ // eslint-disable-next-line no-param-reassign
+ selectorEl.innerHTML = `
+ -
+ ${getValue('choose_create_epsg')}
+
+ ${this.projectionsOptions_.map((proj) => `
+ -
+
+ ${proj.codes[0]}
+
+
+ `).join('')}
+ `;
+ }
+
/**
* Configura el control de entrada de SRS
* @param {String} inputElementId ID del elemento de entrada de SRS
@@ -806,6 +832,7 @@ export default class TemplateCustomizer extends IDEE.Control {
inputElement.addEventListener('focus', () => {
if (!isEditable) {
+ this.refreshProjectionsSelector(selectorElement);
selectorElement.style.display = 'block';
const list = selectorElement.querySelectorAll('li a');
list.forEach((li) => {
@@ -861,42 +888,19 @@ export default class TemplateCustomizer extends IDEE.Control {
const selectorEl = document.querySelector(ID_TEMPLATE_SRS_SELECTOR);
if (currentProjection !== this.projection) {
const currentCenter = previewView.getCenter();
- let transformedCenter;
- try {
- transformedCenter = this.getImpl().transformCoordinates(
- currentCenter,
- currentProjection,
- this.projection,
- );
- } catch (error) {
- try {
- await IDEE.impl.ol.js.projections.setNewProjection(epsg);
- transformedCenter = this.getImpl().transformCoordinates(
- currentCenter,
- currentProjection,
- this.projection,
- );
- } catch (err) {
- this.projection = previousProjection;
- IDEE.dialog.error(`${getValue('exception.srs')} ${this.projection}`);
- return;
- }
+ if (!await IDEE.impl.ol.js.projections.ensureProjection(epsg)) {
+ this.projection = previousProjection;
+ IDEE.dialog.error(`${getValue('exception.srs')} ${this.projection}`);
+ return;
}
+ const transformedCenter = this.getImpl().transformCoordinates(
+ currentCenter,
+ currentProjection,
+ this.projection,
+ );
inputElement.value = this.projection;
- this.projectionsOptions_ = IDEE.impl.ol.js.projections.getSupportedProjs();
- selectorEl.innerHTML = `
- -
- ${getValue('choose_create_epsg')}
-
- ${this.projectionsOptions_.map((proj) => `
- -
-
- ${proj.codes[0]}
-
-
- `).join('')}
- `;
+ this.refreshProjectionsSelector(selectorEl);
const newView = this.getImpl().createView({
projection: this.projection,
diff --git a/api-idee-js/src/plugins/vectorsmanagement/src/facade/js/downloadcontrol.js b/api-idee-js/src/plugins/vectorsmanagement/src/facade/js/downloadcontrol.js
index 29f63dbd5..891bbd04b 100644
--- a/api-idee-js/src/plugins/vectorsmanagement/src/facade/js/downloadcontrol.js
+++ b/api-idee-js/src/plugins/vectorsmanagement/src/facade/js/downloadcontrol.js
@@ -97,12 +97,24 @@ export default class DownloadControl extends IDEE.Control {
* @api
*/
downloadLayer() {
- const noTextLayer = this.newNoTextLayer();
- if (noTextLayer.getFeatures().length > 0) {
- noTextLayer.setVisible(false);
- this.map_.addLayers(noTextLayer);
- const geojsonLayer = noTextLayer.toGeoJSON();
- this.map_.removeLayers(noTextLayer);
+ const featuresGeoJson = [];
+ const textFeatures = [];
+ this.layer_.getFeatures().forEach((feature) => {
+ const style = feature.getStyle();
+ if (!style || style.get('label') === undefined) {
+ featuresGeoJson.push(feature.getGeoJSON());
+ } else {
+ textFeatures.push(feature);
+ }
+ });
+
+ if (featuresGeoJson.length > 0 || textFeatures.length > 0) {
+ const nonTextConverted = IDEE.impl.utils.geojsonTo4326(
+ featuresGeoJson,
+ this.map_.getProjection().code,
+ );
+ const textConverted = this.getTextFeaturesGeoJSON(textFeatures);
+ const geojsonLayer = { type: 'FeatureCollection', features: [...nonTextConverted, ...textConverted] };
this.download(geojsonLayer);
} else {
IDEE.dialog.info(getValue('exception.emptylayer'));
@@ -119,19 +131,48 @@ export default class DownloadControl extends IDEE.Control {
const features = this.managementControl_.getSelectedFeatures();
if (features.length > 0) {
const featuresGeoJson = [];
+ const textFeatures = [];
features.forEach((f) => {
const style = f.getStyle();
if (!style || style.get('label') === undefined) {
featuresGeoJson.push(f.getGeoJSON());
+ } else {
+ textFeatures.push(f);
}
});
- const geojsonLayer = { type: 'FeatureCollection', features: IDEE.impl.utils.geojsonTo4326(featuresGeoJson, this.map_.getProjection().code) };
+ const nonTextConverted = IDEE.impl.utils.geojsonTo4326(
+ featuresGeoJson,
+ this.map_.getProjection().code,
+ );
+ const textConverted = this.getTextFeaturesGeoJSON(textFeatures);
+ const geojsonLayer = { type: 'FeatureCollection', features: [...nonTextConverted, ...textConverted] };
this.download(geojsonLayer);
} else {
IDEE.dialog.info(getValue('exception.featuresel'));
}
}
+ /**
+ * Converts text features to GeoJSON Point features with label properties.
+ * @public
+ * @function
+ * @api
+ * @param {Array} features
+ * @returns {Array}
+ */
+ getTextFeaturesGeoJSON(features) {
+ const textFeaturesGeoJson = features.map((feature) => {
+ const featureGeoJson = feature.getGeoJSON();
+ const style = feature.getStyle();
+ featureGeoJson.properties = featureGeoJson.properties || {};
+ featureGeoJson.properties.lbl_txt = style.get('label.text') || '';
+ featureGeoJson.properties.lbl_font = style.get('label.font') || '';
+ featureGeoJson.properties.lbl_clr = style.get('label.color') || '';
+ return featureGeoJson;
+ });
+ return IDEE.impl.utils.geojsonTo4326(textFeaturesGeoJson, this.map_.getProjection().code);
+ }
+
/**
* Create geojson, kml or shp file download link
* @public
@@ -193,22 +234,6 @@ export default class DownloadControl extends IDEE.Control {
this.managementControl_.deactive(document, 'm-vectorsmanagement-download');
}
- /**
- * Creates vector layer copy of selectedLayer excluding text features.
- * @public
- * @function
- * @api
- * @returns {IDEE.layer.Vector}
- */
- newNoTextLayer() {
- const newLayer = new IDEE.layer.Vector({ name: 'copia' });
- const noTextFeatures = this.layer_.getFeatures().filter((feature) => {
- return feature.getStyle() === null || feature.getStyle().get('label') === undefined;
- });
- newLayer.addFeatures(noTextFeatures, false, true);
- return newLayer;
- }
-
/**
* Parses geojson before shp download.
* Changes geometry type to simple when necessary and removes one pair of brackets.
diff --git a/api-idee-js/src/plugins/vectorsmanagement/test/test.js b/api-idee-js/src/plugins/vectorsmanagement/test/test.js
index 8796b679b..ea0748221 100644
--- a/api-idee-js/src/plugins/vectorsmanagement/test/test.js
+++ b/api-idee-js/src/plugins/vectorsmanagement/test/test.js
@@ -81,7 +81,7 @@ const mp = new VectorsManagement({
// Herramientas
help: true,
addlayer: true,
- selection: false, // Automaticamente desactiva "edition" y "analysis"
+ selection: true, // Si es false automaticamente desactiva "edition" y "analysis"
creation: true,
edition: true,
style: true,
diff --git a/api-idee-js/src/templates/rotateCesium.html b/api-idee-js/src/templates/rotateCesium.html
index 139f311b7..18510e4b9 100644
--- a/api-idee-js/src/templates/rotateCesium.html
+++ b/api-idee-js/src/templates/rotateCesium.html
@@ -15,7 +15,7 @@
-
+
PRUEBA DESARROLLO
-
-
+
diff --git a/api-idee-js/test/development/CP-0003-controls/CP-008.js b/api-idee-js/test/development/CP-0003-controls/CP-008.js
index a9c2d4943..690dc8ba8 100644
--- a/api-idee-js/test/development/CP-0003-controls/CP-008.js
+++ b/api-idee-js/test/development/CP-0003-controls/CP-008.js
@@ -1,15 +1,17 @@
import { map as Mmap } from 'IDEE/api-idee';
-import Plugin from 'IDEE/Plugin';
// import Control from 'IDEE/control/Control';
import Rotate from 'IDEE/control/Rotate';
import * as Position from 'IDEE/ui/position';
const map = Mmap({
container: 'map',
- projection: 'EPSG:3857',
controls: ['rotate'],
- center: [-443273.10081370454, 4757481.749296248],
- zoom: 6,
+ projection: 'EPSG:4326',
+ zoom: 8,
+ center: [
+ -7.68,
+ 43.084999999999994,
+ ],
});
const rotate = new Rotate({
diff --git a/api-idee-js/test/development/CP-0003-controls/CP-011.js b/api-idee-js/test/development/CP-0003-controls/CP-011.js
index 7f132a7c6..ec8c8b365 100644
--- a/api-idee-js/test/development/CP-0003-controls/CP-011.js
+++ b/api-idee-js/test/development/CP-0003-controls/CP-011.js
@@ -2,12 +2,10 @@
import { map as Mmap } from 'IDEE/api-idee';
import ImplementationSwitcher from 'IDEE/control/ImplementationSwitcher';
-// IDEE.config('PROXY_URL', 'https://mapea4-sigc.juntadeandalucia.es/mapea/api/proxy');
-
const map = Mmap({
container: 'map',
projection: 'EPSG:4326',
- controls: ['location'],
+ controls: ['location', 'implementationswitcher'],
zoom: 8,
center: [
-7.68,
@@ -31,7 +29,9 @@ const create = (options) => {
const remove = () => {
const ctrls = map.getControls(ImplementationSwitcher.NAME);
- if (ctrls.length === 1) map.removeControls(ctrls[0]);
+ ctrls.forEach((ctrl) => {
+ map.removeControls(ctrl);
+ });
};
const recreate = () => {
@@ -65,4 +65,6 @@ removeButton.addEventListener('click', () => {
remove();
});
-recreate();
+map.once('load', () => {
+ recreate();
+});
diff --git a/api-idee-rest/src/main/webapp/rotate.jsp b/api-idee-rest/src/main/webapp/rotate.jsp
index 4da48afca..8e8c27983 100644
--- a/api-idee-rest/src/main/webapp/rotate.jsp
+++ b/api-idee-rest/src/main/webapp/rotate.jsp
@@ -87,7 +87,7 @@
maxZoom: 20,
minZoom: 4,
center: [-467062.8225, 4683459.6216],
- controls: ['location']
+ controls: ['implementationswitcher']
});
const layerinicial = new IDEE.layer.WMS({