UNPKG

@ignf-geoportal/sdk-3d

Version:

French Geoportal SDK based on OpenLayers (2D) and iTowns (3D) libraries

528 lines (506 loc) 22.7 kB
import { ItMap } from "./ItMapBase"; import { itownsExtended } from "geoportal-extensions-itowns"; import { WMTSSource, ColorLayer } from "itowns"; /** * Association controlId <-> classe iTowns d'implemenation */ ItMap.CONTROLSCLASSES = { mouseposition : "itowns.control.MousePosition", layerswitcher : "itowns.control.LayerSwitcher", attributions : "itowns.control.Attributions", overview : "itowns.control.MiniGlobe", graphicscale : "itowns.control.Scale", boostrelief : "itowns.control.BoostRelief", buildings : "itowns.control.Buildings" }; /** * Adds mouse position control to the map. * * @param {Object} controlOpts - control options * @param {String|Element} controlOpts.div - target HTML element container. Default is chosen by implementation. * @param {Boolean} controlOpts.maximised - if the control has to be opened or not. * @param {Array.<Object>} controlOpts.systems - List of coordinates systems available for display. * @param {String} controlOpts.systems.crs - Coordinates system ID. * @param {String} controlOpts.systems.label - label used to designate the CRS. * @param {String} controlOpts.systems.type - "Geographical" or "Metric" * @param {Array.<String>} controlOpts.units - units used for coordinates display ("m", "km" for Metric coordinates, "dec", "dms", "rad" or "gon" for geographical coordinates). * @param {Boolean} controlOpts.displayAltitude - (de)activate altitude display * @param {Boolean} controlOpts.displayCoordinates - (de)activate planimetric coorinates display. * @param {Object} controlOpts.altitude - altitude interaction specific configuration. Implementation specific. * * @returns {Object} control - mousePosition control */ ItMap.prototype.addMousePositionControl = function (controlOpts) { var mpOpts = {}; if (controlOpts.div) { mpOpts.target = controlOpts.div; } mpOpts.collapsed = !controlOpts.maximised; if (!this._isConfLoaded) { mpOpts.apiKey = this.apiKey; } if (controlOpts.systems && Array.isArray(controlOpts.systems) && controlOpts.systems.length > 0) { for (var i = 0; i < controlOpts.systems.length; i++) { /* if (!ol.proj.get(controlOpts.systems[i].crs)) { // on retire les systèmes non définis this.logger.trace("[ItMap] addMousePositionControl : crs [" + controlOpts.systems[i].crs + "] not found." ) ; continue ; } */ if (!mpOpts.systems) { mpOpts.systems = []; } mpOpts.systems.push(controlOpts.systems[i]); } } if (controlOpts.units && Array.isArray(controlOpts.units) && controlOpts.units.length > 0) { mpOpts.units = []; for (var j = 0; j < controlOpts.units.length; j++) { if (typeof controlOpts.units[j] === "string") { this.logger.trace("[ItMap] addMousePositionControl : adding unit [" + controlOpts.units[j].toUpperCase()); mpOpts.units.push(controlOpts.units[j]); } } } mpOpts.displayAltitude = controlOpts.displayAltitude; mpOpts.displayCoordinates = controlOpts.displayCoordinates; if (controlOpts.altitude) { mpOpts.altitude = controlOpts.altitude; } var control = new itownsExtended.control.MousePosition(mpOpts); this.libMap.addWidget(control); if (!isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (!isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } return control; }; /** * Adds LayerSwitcher control to the map. * * @param {Object} controlOpts - control options * @param {String|Element} controlOpts.div - target HTML element container. Default is chosen by implementation. * @param {Boolean} controlOpts.maximised - if the control has to be opened or not. * * @returns {Object} control - layerSwitcher control */ ItMap.prototype.addLayerSwitcherControl = function (controlOpts) { this.logger.trace("[ItMap] : addLayerSwitcherControl ... "); // TODO : parametrage des couches var lsOpts = { layers : (controlOpts && controlOpts.layers) || [], options : { collapsed : !(controlOpts && controlOpts.maximised) } }; if (controlOpts && controlOpts.div) { lsOpts.options.target = controlOpts.div; } // application des configuration des couches : for (var i = 0; i < this._layers.length; i++) { var layer = this._layers[i]; // Si la couche est un MNT, on ne l'ajoute pas au layerSwitcher if (layer.options.format.toLowerCase() !== "kml" && layer.options.format.toLowerCase() !== "compute" && layer.obj.type !== "color" && !layer.obj.isColorLayer) { continue; } this.logger.trace("[ItMap] : layerSwitcher : configuring layer : " + layer.id); // INFO : les couches Geoportail sont aussi configurées. var layerConf = { id : layer.id, layer : layer.obj, config : {} }; if (layer.options.title) { this.logger.trace("[ItMap] : layerSwitcher : setting title to [" + layer.options.title + "] for layer " + layer.id); layerConf.config.title = layer.options.title; } if (layer.options.description) { this.logger.trace("[ItMap : layerSwitcher : setting description to [" + layer.options.description + "] for layer " + layer.id); layerConf.config.description = layer.options.description; } if (layer.options.quicklookUrl) { this.logger.trace("[ItMap] : layerSwitcher : setting quicklookUrl to [" + layer.options.quicklookUrl + "] for layer " + layer.id); layerConf.config.quicklookUrl = layer.options.quicklookUrl; } if (layer.options.legends) { this.logger.trace("[ItMap] : layerSwitcher : setting legends to [" + layer.options.legends + "] for layer " + layer.id); layerConf.config.legends = layer.options.legends; } if (layer.options.metadata) { this.logger.trace("[ItMap] : layerSwitcher : setting metadata to [" + layer.options.metadata + "] for layer " + layer.id); layerConf.config.metadata = layer.options.metadata; } lsOpts.layers.push(layerConf); } this.logger.trace("[ItMap] : layerSwitcher Opts : ... "); var control = new itownsExtended.control.LayerSwitcher(lsOpts); this.libMap.addWidget(control); // modify the position of the layerswitcher button if x or y is given as option if (controlOpts && !isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (controlOpts && !isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } return control; }; /** * Adds overview map to the map. * * @param {Object} controlOpts - control options * @param {HTMLElement} controlOpts.div - The HTML Element where the overview is put * @param {Boolean} controlOpts.maximised - Display or not the control * @param {String} controlOpts.layerId - The Geoportal layerId of the miniGlobeLayer (by default, "ORTHOIMAGERY.ORTHOPHOTOS") * @param {Object} controlOpts.layer - The layer object formatted as expected by itowns (layerId ignored if layer param specified) * @param {String} controlOpts.position - The type of positionment of the overview element inside its container ("relative or absolute", by default) * @param {Number} controlOpts.width - The width of the minimap (100px by default) * @param {Number} controlOpts.height - The height of the minimap (100px by default) * @param {Number} controlOpts.x - The position of the minimap from the left of the container div (20px by default) * @param {Number} controlOpts.y - The position of the minimap from the bottom of the container div (20px by default) * * @returns {Object} control - overview control */ ItMap.prototype.addOverviewControl = function (controlOpts) { this.logger.trace("[ItMap] addOverviewControl : ... "); // clone car on ne veut pas modifier l'original ! var opts = JSON.parse(JSON.stringify(controlOpts)); var ovControlOptions = {}; if (opts.position) { ovControlOptions.position = opts.position; } else { ovControlOptions.position = "absolute"; } if (opts.div) { ovControlOptions.target = opts.div; } if (opts.layer) { ovControlOptions.layer = opts.layer; // conf d'une couche, possibilité de ne pas utiliser la configuration ! if (!this._isConfLoaded) { ovControlOptions.layer.apiKey = this.apiKey; } // on ajoute les limites du tileMatrix if (!opts.layer.source.tileMatrixSet) { ovControlOptions.layer.source.tileMatrixSet = "PM"; } if (!opts.layer.source.tileMatrixSetLimits) { ovControlOptions.layer.source.tileMatrixSetLimits = this._getTMSLimits(opts.layer.source.tileMatrixSet); } ovControlOptions.layer.source = new WMTSSource(ovControlOptions.layer.source); ovControlOptions.layer = new ColorLayer(ovControlOptions.layer.id, ovControlOptions.layer); } else if (controlOpts.layerId) { // utilisation de la config ! ovControlOptions.layer = new itownsExtended.layer.GeoportalWMTS({ layer : controlOpts.layerId, ssl : true }); } else { // orthophotos layer by default on the miniglobe // utilisation de la config ! ovControlOptions.layer = new itownsExtended.layer.GeoportalWMTS({ layer : "ORTHOIMAGERY.ORTHOPHOTOS", ssl : true }); } var control = new itownsExtended.control.MiniGlobe(ovControlOptions); this.libMap.addWidget(control); if (control.getElement()) { // hide the div if maximised option = false if (controlOpts.maximised === false) { control.getElement().style.display = "none"; } else { control.getElement().style.display = "inline"; } // modify the size of the miniglobe if width or height is given as option if (!isNaN(controlOpts.width)) { control.getElement().style.width = controlOpts.width + "px"; control.getElement().getElementsByTagName("canvas")[0].style.width = controlOpts.width + "px"; } if (!isNaN(controlOpts.height)) { control.getElement().style.height = controlOpts.height + "px"; control.getElement().getElementsByTagName("canvas")[0].style.height = controlOpts.height + "px"; } // modify the position of the miniglobe if x or y is given as option if (!isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (!isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } // update the canvas to fit with the overview element size var elementSize = {}; elementSize.width = parseFloat(control.getElement().style.width) || 100; elementSize.height = parseFloat(control.getElement().style.height) || 100; control._globeObj.resize(elementSize.width, elementSize.height); } return control; }; /** * Adds the graphic scale control to the map * * @param {Object} controlOpts - control options * @param {HTMLElement} controlOpts.div - The HTML Element where the scalebar is put * @param {Boolean} controlOpts.maximised - Display or not the control * @param {Number} controlOpts.x - The position of the minimap from the left of the container div (20px by default) * @param {Number} controlOpts.y - The position of the minimap from the bottom of the container div (20px by default) * * @returns {Object} control - graphic scale control */ ItMap.prototype.addGraphicScaleControl = function (controlOpts) { this.logger.trace("[ItMap] addGraphicScaleControl..."); var scaleControlOptions = {}; if (controlOpts.position) { scaleControlOptions.position = controlOpts.position; } else { scaleControlOptions.position = "absolute"; } if (controlOpts.div) { scaleControlOptions.target = controlOpts.div; } var control = new itownsExtended.control.Scale(scaleControlOptions); this.libMap.addWidget(control); if (control.getElement()) { // hide the div if maximised option = false if (controlOpts.maximised === false) { control.getElement().style.display = "none"; } else { control.getElement().style.display = "inline"; } // modify the position of the scaleBar if x or y is given as option if (!isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (!isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } } return control; }; /** * Adds the attributions control to to the map * * @param {Object} controlOpts - control options * * @returns {Object} control - attributions control */ ItMap.prototype.addAttributionsControl = function (controlOpts) { var attOpts = {}; attOpts.options = {}; if (controlOpts.div) { attOpts.options.target = controlOpts.div; } attOpts.options.collapsed = !controlOpts.maximised; var control = new itownsExtended.control.Attributions(attOpts); this.libMap.addWidget(control); return control; }; /** * Adds the boostRelief control to the map * * @param {Object} controlOpts - control options * @param {HTMLElement} controlOpts.div - The HTML Element where the boostrelief control is put * @param {Boolean} controlOpts.maximised - Display or not the control * @param {Number} [controlOpts.x] - The position of the boostRelief button from the left of the container div * @param {Number} [controlOpts.y] - The position of the boostRelief button from the bottom of the container div * @param {Object} [controlOpts.scale] - Defines the scale used to boost the relief * @param {Number} [controlOpts.scale.min] - Minimum of the scale - 1 by default * @param {Number} [controlOpts.scale.max] - Maximum of the scale - 50 by default * @param {Number} [controlOpts.scale.step] - Step of the scale - 1 by default * @param {Number} [controlOpts.defaultBoost = 1] - Default boost value applied to the widget and the elevation layers when loaded * * @returns {Object} control - boostRelief Control */ ItMap.prototype.addBoostReliefControl = function (controlOpts) { this.logger.trace("[ItMap] addBoostReliefControl..."); var boostReliefControlOptions = {}; if (controlOpts.position) { boostReliefControlOptions.position = controlOpts.position; } else { boostReliefControlOptions.position = "absolute"; } if (controlOpts.div) { boostReliefControlOptions.target = controlOpts.div; } if (controlOpts.scale) { boostReliefControlOptions.scale = controlOpts.scale; } if (controlOpts.defaultBoost) { boostReliefControlOptions.defaultBoost = controlOpts.defaultBoost; } var control = new itownsExtended.control.BoostRelief(boostReliefControlOptions); this.libMap.addWidget(control); if (control.getElement()) { // hide the div if maximised option = false if (controlOpts.maximised === false) { control.getElement().style.display = "none"; } else { control.getElement().style.display = "inline"; } // modify the position of the boostRelief button if x or y is given as option if (!isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (!isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } } return control; }; /** * Adds the buildings control to the globe * * @param {Object} controlOpts - control options * @param {Boolean} controlOpts.maximised - Display or not the control * @param {Number} [controlOpts.x] - The position of the buildings button from the left of the container div * @param {Number} [controlOpts.y] - The position of the buildings button from the bottom of the container div * @param {HTMLElement} controlOpts.div - The HTML Element where the scalebar is put * @param {Boolean} [controlOpts.MNT = true] - adds the MNT to the globe (ELEVATION.ELEVATIONGRIDCOVERAGE.HIGHRES) * @param {Boolean} [controlOpts.buildingsOnGround = false] - If true, put the buildings without elevation * @param {Number} [controlOpts.defaultVisibility = true] - Display the building when the globe is initialized * @param {Number} [controlOpts.minZoom = 15] - Minimum zoom level to display the buildings. * * @returns {Object} control - buildings Control */ ItMap.prototype.addBuildingsControl = function (controlOpts) { this.logger.trace("[ItMap] addBuildingsControl..."); var buildingsControlOptions = controlOpts; var control = new itownsExtended.control.Buildings(buildingsControlOptions); this.libMap.addWidget(control); if (control.getElement()) { // hide the div if maximised option = false if (buildingsControlOptions.maximised === false) { control.getElement().style.display = "none"; } else { control.getElement().style.display = "inline"; } // modify the position of the buildings button if x or y is given as option if (!isNaN(controlOpts.x)) { control.getElement().style.left = Number(controlOpts.x) + "px"; control.getElement().style.right = "unset"; } if (!isNaN(controlOpts.y)) { control.getElement().style.bottom = Number(controlOpts.y) + "px"; control.getElement().style.top = "unset"; } } return control; }; /** * Removes the listed controls of the map. * * @param {Array.<String>} controlIds - A list of control's id or null. */ ItMap.prototype.removeControls = function (controlIds) { this.logger.trace("[ItMap] : removeControls ... "); if (!controlIds || (Array.isArray(controlIds) && controlIds.length === 0)) { this.logger.info("No control to remove."); return; } if (!Array.isArray(controlIds)) { controlIds = [controlIds]; } var controlId = null; for (var i = 0; i < controlIds.length; i++) { controlId = controlIds[i]; var idx = this._findRegisteredControl(controlId); if (idx >= 0) { this.logger.trace("[ItMap] : removeControls : removing [" + controlId + "] from register."); this._controls.splice(idx, 1); } var itownsControl = this.getLibMapControl(controlId); if (!itownsControl) { this.logger.info("Impossible to remove control [" + controlId + "] : not found or unhandled"); continue; } this.logger.trace("[ItMap] : removeControls : removing [" + controlId + "] from Map."); this.libMap.removeWidget(itownsControl); } }; /** * Returns implementation of the control * * @param {String} controlId - identifier of the control * @returns {Object} - implementation object of the control if it is on the map. null otherwise. */ ItMap.prototype.getLibMapControl = function (controlId) { var foundItControl = null; // verifications de base : controlId est bien gere. if (!ItMap.CONTROLSCLASSES.hasOwnProperty(controlId.toLowerCase()) || !ItMap.CONTROLSCLASSES[controlId.toLowerCase()]) { this.logger.trace("[ItMap] getLibMapControl : control " + controlId + " non implémenté."); return foundItControl; } // on regarde du cote des controles var itControls = this.libMap.getWidgets(); if (!itControls || itControls.length === 0) { this.logger.trace("[ItMap] getLibMapControl : no control found on map"); return foundItControl; } for (var j = 0; j < itControls.length; j++) { this.logger.trace("[ItMap] getLibMapControl : analyzing : " + controlId); // test on control Name if (itControls[j]._name && itControls[j]._name.toLowerCase() === controlId.toLowerCase()) { foundItControl = itControls[j]; this.logger.trace("[ItMap] getLibMapControl : found GP Plugin Control ! "); break; } } if (!foundItControl) { this.logger.trace("[ItMap] getLibMapControl : control " + controlId + " not found ! "); } return foundItControl; }; /** * Gets Layer Container div ID for a given layerId. * * @param {String} layerId - layer identifier * @returns {String} - Layer Container div Id in the LayerSwitcher */ ItMap.prototype.getLSLayerContainerDivId = function (layerId) { var id = null; var idxLS = this._findRegisteredControl("layerswitcher"); if (idxLS < 0) { this.logger.trace("[ItMap] : getLSLayerContainerDivId : no layerswitcher on map !"); return id; } var itlayers = this._getLayersObj([layerId]); if (itlayers && itlayers.length > 0) { var itLayerList = this._controls[idxLS].obj._layerListContainer; if (itLayerList) { var divId = itLayerList.id; var uid = divId.substring(divId.indexOf("-")); if (itLayerList.childNodes) { for (var layerDivKey = 0; layerDivKey < itLayerList.childNodes.length; layerDivKey++) { if (itLayerList.childNodes[layerDivKey].id === "GPlayerSwitcher_ID_" + layerId + uid) { var foundId = "GPlayerSwitcher_ID_" + layerId + uid; return foundId; } } } } } this.logger.trace("[ItMap] : getLSLayerContainerDivId : layer [" + layerId + "] not found on map !"); return id; };