UNPKG

geopf-extensions-openlayers

Version:

French Geoportal Extensions for OpenLayers libraries

546 lines (479 loc) 17.6 kB
// import OpenLayers import Overlay from "ol/Overlay"; import { Draw as DrawInteraction } from "ol/interaction"; import { Fill, Stroke, Style, Circle } from "ol/style"; import VectorLayer from "ol/layer/Vector"; import VectorSource from "ol/source/Vector"; // import local import Logger from "../../Utils/LoggerByDefault"; import Interactions from "../Utils/Interactions"; // import local with ol dependencies import LayerSwitcher from "../LayerSwitcher/LayerSwitcher"; // Derived from OpenLayers measure example // http://openlayers.org/en/latest/examples/measure.html var logger = Logger.getLogger("measures"); /** * @type {ol.control.Measures} * @abstract * Measures Tools : * - length * - aera * - azimut */ var Measures = { // ****************************************************************** // // > Default Styles // ****************************************************************** // /* * Pointer */ DEFAULT_POINTER_STYLE : new Circle({ radius : 5, stroke : new Stroke({ color : "#002A50", width : 2 }), fill : new Fill({ color : "rgba(255, 155, 0, 0.7)" }) }), /* * Measures style line */ DEFAULT_DRAW_START_STYLE : new Style({ fill : new Fill({ color : "rgba(0, 183, 152, 0.2)" }), stroke : new Stroke({ color : "#002A50", lineDash : [10, 10], width : 2 }) }), /* * Measures final style line */ DEFAULT_DRAW_FINISH_STYLE : new Style({ fill : new Fill({ color : "rgba(0, 183, 152, 0.3)" }), stroke : new Stroke({ color : "#002A50", width : 3 }) }), // ****************************************************************** // // > ToolBox : these tools work together // ****************************************************************** // // sample : // tools[name_control][0].(active|instance|map) // tools : { // MeasureLength : [ // { active : true, instance : [Object MeasureLength], map : "map1" }, // { active : true, instance : [Object MeasureLength], map : "map2" } // ], // MeasureArea : [], // MeasureAzimuth : [] // } tools : { MeasureLength : [], MeasureArea : [], MeasureAzimuth : [] }, // ****************************************************************** // // > Variables // ****************************************************************** // /** * Global measure draw interaction * @type {ol.interaction.Draw} */ measureDraw : null, /** * Global vector source for measure * @type {ol.source.Vector} */ measureSource : null, /** * Global vector layer for measure * @type {ol.layer.Vector} */ measureVector : null, /** * Event on removing map layer * @type {ol.CollectionEventType} */ eventLayerRemove : null, /** * Currently drawn feature. * @type {ol.Feature} */ sketch : null, /** * The measure tooltip element. * @type {Element} */ measureTooltipElement : null, /** * Overlay to show the measurement. * @type {ol.Overlay} */ measureTooltip : null, /** * TODO The help tooltip element. * @type {Element} */ helpTooltipElement : null, /** * TODO Overlay to show the help. * @type {ol.Overlay} */ helpTooltip : null, // ****************************************************************** // // > Methods Public // ****************************************************************** // /** Desactived Tool Measure */ clean : function () { var _class = this.CLASSNAME; logger.trace("[" + _class + "] deactived tool !"); // sur la desactivation de l'outil de mesure // on fait un nettoyage des ressources // ainsi que le DOM this.clearMeasure(); this.clearMeasureToolTip(); this.removeMeasureEvents(); this._pictoContainer.setAttribute("aria-pressed", false); }, // ****************************************************************** // // > Methods Events // ****************************************************************** // /** * Handle pointer move. * * @param {ol.MapBrowserEvent} e - The event. */ onPointerMoveHandler : function (e) { if (e.dragging) { return; } /** @type {ol.Coordinate|undefined} */ var tooltipCoord = e.coordinate; if (this.sketch) { var output; var geom = (this.sketch.getGeometry()); output = this.format((geom)); if (geom.getType() === "LineString") { tooltipCoord = geom.getLastCoordinate(); } else if (geom.getType() === "Polygon") { tooltipCoord = geom.getInteriorPoint().getCoordinates(); } else { return; } this.measureTooltipElement.innerHTML = output; this.measureTooltip.setPosition(tooltipCoord); } }, /** * Main program ! * This method is called by event 'click' on control picto * * @param {Object} e - HTMLElement * @param {String} type - LineString or Polygon * @private */ onShowMeasureClick : function (e, type) { if (e.target.ariaPressed === "true") { this.onPanelOpen(); } var map = this.getMap(); var currentMapId = map.getTargetElement().id; // contexte d'execution var context = typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : null; if (context) { // Pour info // les objets de mesures ont du code partagé // (afin de gerer les interactions entre eux). // Dans un mode "modules", on partage cet objet (this.tools) via le contexte // d'execution (ex. avec window) this.tools = context.gpShareMeasures || {}; } // desactivation des controles de mesures sur la carte courrante var mySelf = this.CLASSNAME; // this.constructor.name : pas possible en mode minifié/manglifié ! for (var className in this.tools) { if (this.tools.hasOwnProperty(className)) { var measures = this.tools[className]; for (var i = 0; i < measures.length; i++) { var o = measures[i]; if (o && o.active && className !== mySelf && o.map.id === currentMapId) { o.active = false; if (o.instance !== null) { // au cas où le controle a été supprimé ! o.instance.clean(); } } } } } // desactivation des autres interactions parasites Interactions.unset(map, { current : "Measures" }); var opened = this._pictoContainer.ariaPressed; if (opened === "true") { this.addMeasureEvents(); this.initMeasureInteraction(); this.addMeasureInteraction(type); for (var j = 0; j < this.tools[mySelf].length; j++) { if (this.tools[mySelf][j].map.id === currentMapId) { this.tools[mySelf][j].active = true; } } } else { this.clearMeasure(); this.clearMeasureToolTip(); this.removeMeasureEvents(); for (var k = 0; k < this.tools[mySelf].length; k++) { if (this.tools[mySelf][k].map.id === currentMapId) { this.tools[mySelf][k].active = false; } } } }, // ****************************************************************** // // > Methods not Public // ****************************************************************** // /** * Clear all dom tooltip of length, area or azimut object. */ clearMeasureToolTip : function () { var map = this.getMap(); if (!map) { return; } var mapContainer = map.getTargetElement(); // au cas où il y'aurait plusieurs container de carte ! var overlays = mapContainer.getElementsByClassName("ol-overlaycontainer"); for (var k = 0; k < overlays.length; k++) { var nodes = overlays[k]; var len = nodes.children.length; var nodesToRemove = []; for (var i = 0; i < len; i++) { var node = nodes.children[i]; if (node.children.length !== 0) { var child = node.children[0]; if (child.className === "GPmeasureTooltip GPmeasureTooltip-static" || child.className === "GPmeasureTooltip GPmeasureTooltip-measure") { nodesToRemove.push(node); } } } for (var j = 0; j < nodesToRemove.length; j++) { nodes.removeChild(nodesToRemove[j]); } } }, /** * Clear all length, area or azimut object. */ clearMeasure : function () { var map = this.getMap(); // FIXME !? // if (this.measureTooltip) { // map.removeOverlay(this.measureTooltip); // this.measureTooltip = null; // } if (this.measureVector) { map.removeLayer(this.measureVector); this.measureVector = null; } if (this.measureDraw) { map.removeInteraction(this.measureDraw); this.measureDraw = null; } }, /** * Creates a new measure tooltip * FIXME bug d'affichage de la tooltip de saisie en cours si on ne termine pas * la saisie !? * * @param {ol.Map} map - The Map. */ createMeasureTooltip : function (map) { if (this.measureTooltipElement) { this.measureTooltipElement.parentNode.removeChild(this.measureTooltipElement); } this.measureTooltipElement = document.createElement("div"); this.measureTooltipElement.className = "GPmeasureTooltip GPmeasureTooltip-measure"; this.measureTooltip = new Overlay({ element : this.measureTooltipElement, stopEvent : false, offset : [0, -15], positioning : "bottom-center" }); map.addOverlay(this.measureTooltip); }, /** * TODO evolution * Creates a new help tooltip * * @param {ol.Map} map - The Map. */ createHelpTooltip : function (map) { if (this.helpTooltipElement) { this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement); } this.helpTooltipElement = document.createElement("div"); this.helpTooltipElement.className = "tooltip hidden"; this.helpTooltip = new Overlay({ element : this.helpTooltipElement, stopEvent : false, offset : [15, 0], positioning : "center-left" }); map.addOverlay(this.helpTooltip); }, /** * Creates a style for drawing * * @param {Object} styles - styles. */ createStylingMeasureInteraction : function (styles) { this.options.styles = styles || {}; // style de depart logger.trace("style start", this.options.styles.start); // Creation à partir des styles par défaut var startStyleOpts = { image : Measures.DEFAULT_POINTER_STYLE, fill : Measures.DEFAULT_DRAW_START_STYLE.getFill(), stroke : Measures.DEFAULT_DRAW_START_STYLE.getStroke() }; // ecrasement à partir des propriétés renseignées if (this.options.styles.hasOwnProperty("pointer") && this.options.styles.pointer instanceof Image) { startStyleOpts.image = this.options.styles.pointer; } if (this.options.styles.hasOwnProperty("start") && this.options.styles.start instanceof Style) { if (this.options.styles.start.getFill() != null) { startStyleOpts.fill = this.options.styles.start.getFill(); } if (this.options.styles.start.getStroke() != null) { startStyleOpts.stroke = this.options.styles.start.getStroke(); } } this.options.styles.start = new Style(startStyleOpts); // style de fin logger.trace("style finish", this.options.styles.finish); var finishStyleOpts = { fill : Measures.DEFAULT_DRAW_FINISH_STYLE.getFill(), stroke : Measures.DEFAULT_DRAW_FINISH_STYLE.getStroke() }; // ecrasement à partir des propriétés renseignées if (this.options.styles.hasOwnProperty("finish") && this.options.styles.finish instanceof Style) { if (this.options.styles.finish.getFill() != null) { finishStyleOpts.fill = this.options.styles.finish.getFill(); } if (this.options.styles.finish.getStroke() != null) { finishStyleOpts.stroke = this.options.styles.finish.getStroke(); } } this.options.styles.finish = new Style(finishStyleOpts); }, /** * Add the measure interaction * * @param {String} type - LineString or Polygon. */ addMeasureInteraction : function (type) { var map = this.getMap(); // Creates and adds the interaction var self = this; this.measureDraw = new DrawInteraction({ source : this.measureSource, // condition : permet de gerer la suppression des derniers points saisis condition : function (event) { if (event.originalEvent.ctrlKey) { if (self.sketch) { this.removeLastPoint(); } return false; } return true; }, type : type, style : this.options.styles.start || Measures.DEFAULT_DRAW_START_STYLE }); this.measureDraw.setProperties({ name : "Measures", source : this }); map.addInteraction(this.measureDraw); // Create tooltips this.createMeasureTooltip(map); // Event start measuring this.measureDraw.on("drawstart", (evt) => { // set sketch self.sketch = evt.feature; }); // Event end measuring this.measureDraw.on("drawend", () => { // FIXME MaJ de la tooltip en mode mobile ! if (self.sketch) { var output; var tooltipCoord; var geom = (self.sketch.getGeometry()); output = self.format((geom)); if (geom.getType() === "LineString") { tooltipCoord = geom.getLastCoordinate(); } else if (geom.getType() === "Polygon") { tooltipCoord = geom.getInteriorPoint().getCoordinates(); } else { return; } self.measureTooltipElement.innerHTML = output; self.measureTooltip.setPosition(tooltipCoord); } self.measureTooltipElement.className = "GPmeasureTooltip GPmeasureTooltip-static"; self.measureTooltip.setOffset([0, -7]); // unset sketch self.sketch = null; // unset tooltip so that a new one can be created self.measureTooltipElement = null; self.createMeasureTooltip(map); }); }, /** * Init the measure interaction */ initMeasureInteraction : function () { var map = this.getMap(); this.measureSource = new VectorSource(); this.measureVector = new VectorLayer({ source : this.measureSource, style : this.options.styles.finish || Measures.DEFAULT_DRAW_FINISH_STYLE }); // on rajoute le champ gpResultLayerId permettant d'identifier une couche crée par le composant. this.measureVector.gpResultLayerId = "measure"; map.addLayer(this.measureVector); // Si un layer switcher est présent dans la carte, on lui affecte des informations pour cette couche map.getControls().forEach( (control) => { if (control.CLASSNAME === "LayerSwitcher") { // un layer switcher est présent dans la carte var layerId = this.measureVector.gpLayerId; // on n'ajoute des informations que s'il n'y en a pas déjà (si le titre est le numéro par défaut) if (control._layers[layerId].title === layerId) { control.addLayer( this.measureVector, { title : this.options.layerDescription.title, description : this.options.layerDescription.description } ); } } } ); } }; export default Measures;