Fix lat/lon vs. lon/lat issues
[gpl/argeo-suite.git] / js / src / geo / OpenLayersMapPart.js
index 0e32e8832c410226de3e2c56fd9e6df105f671d1..d033e303df5583b96850d2f714b116bde8c2857e 100644 (file)
@@ -2,39 +2,65 @@
  * @module OpenLayersMapPart
  */
 
-import Map from 'ol/Map.js';
-import View from 'ol/View.js';
 import { fromLonLat, getPointResolution } from 'ol/proj.js';
-import VectorSource from 'ol/source/Vector.js';
-import Feature from 'ol/Feature.js';
-import { Point } from 'ol/geom.js';
-import VectorLayer from 'ol/layer/Vector.js';
-import GeoJSON from 'ol/format/GeoJSON.js';
-import GPX from 'ol/format/GPX.js';
+
+import TileLayer from 'ol/layer/Tile.js';
+
+import OSM from 'ol/source/OSM.js';
+import { isEmpty } from 'ol/extent';
+
 import Select from 'ol/interaction/Select.js';
 import Overlay from 'ol/Overlay.js';
-import { Style, Icon } from 'ol/style.js';
-import { transformExtent } from 'ol/proj.js';
+
+import Map from 'ol/Map.js';
+
+import { OverviewMap, ScaleLine, defaults as defaultControls } from 'ol/control.js';
+import { easeOut } from 'ol/easing';
 
 import * as SLDReader from '@nieuwlandgeo/sldreader';
 
 import MapPart from './MapPart.js';
+import { transformToOlLonLatExtent } from './OpenLayersUtils.js';
 
 /** OpenLayers implementation of MapPart. */
 export default class OpenLayersMapPart extends MapPart {
        /** The OpenLayers Map. */
        #map;
 
+       /** The overview map */
+       #overviewMap;
+
        /** Styled layer descriptor */
        #sld;
 
+       /** The select interaction */
+       select;
+
        /** Externally added callback functions. */
        callbacks = {};
 
        /** Constructor taking the mapName as an argument. */
        constructor(mapName) {
                super(mapName);
+               this.#overviewMap = new OverviewMap({
+                       layers: [
+                               new TileLayer({
+                                       source: new OSM(),
+                               }),
+                       ],
+               });
+               this.select = new Select();
                this.#map = new Map({
+                       controls: defaultControls({
+                               attribution: false,
+                               rotate: false,
+                       }).extend([this.#overviewMap, new ScaleLine({
+                               bar: false,
+                               steps: 2,
+                               text: false,
+                               minWidth: 150,
+                               maxWidth: 200,
+                       })]),
                        layers: [
                        ],
                        //                                              view: new View({
@@ -44,67 +70,22 @@ export default class OpenLayersMapPart extends MapPart {
                        //                                              }),
                        target: this.getMapName(),
                });
+               this.#map.addInteraction(this.select);
                //this.#map.getView().set('projection', 'EPSG:4326', true);
        }
 
        /* GEOGRAPHICAL METHODS */
 
-       setZoom(zoom) {
-               this.#map.getView().setZoom(zoom);
-       }
-
        setCenter(lat, lon) {
                this.#map.getView().setCenter(fromLonLat([lon, lat]));
        }
 
        fit(extent, options) {
-               var transformed = transformExtent(extent, 'EPSG:4326', this.#map.getView().getProjection());
+               var transformed = transformToOlLonLatExtent(extent, this.#map.getView().getProjection());
                this.#map.getView().fit(transformed, options);
        }
 
-       addPoint(lng, lat, style) {
-               let vectorSource = new VectorSource({
-                       features: [new Feature({
-                               geometry: new Point(fromLonLat([lng, lat]))
-                       })]
-               });
-               this.#map.addLayer(new VectorLayer({
-                       source: vectorSource,
-                       style: style,
-               }));
-       }
-
-       addUrlLayer(url, format, style, sld) {
-               let featureFormat;
-               if (format === 'GEOJSON') {
-                       featureFormat = new GeoJSON();
-               }
-               else if (format === 'GPX') {
-                       featureFormat = new GPX();
-               } else {
-                       throw new Error("Unsupported format " + format);
-               }
-               const vectorSource = new VectorSource({
-                       url: url,
-                       format: featureFormat,
-               });
-               const vectorLayer = new VectorLayer({
-                       source: vectorSource,
-               });
-               if (sld) {
-                       this.#applySLD(vectorLayer, style);
-               } else if (style !== null) {
-                       vectorLayer.setStyle(style);
-               }
-               this.#map.addLayer(vectorLayer);
-       }
-
-       addLayer(js) {
-               const func = new Function(js);
-               const layer = (func)();
-               this.#map.addLayer(layer);
-       }
-
+       /** Accessors */
        getMap() {
                return this.#map;
        }
@@ -134,7 +115,7 @@ export default class OpenLayersMapPart extends MapPart {
                                return true;
                        });
                        if (feature !== null)
-                               mapPart.callbacks['onFeatureSingleClick'](feature.get('path'));
+                               mapPart.callbacks['onFeatureSingleClick'](feature.get('cr:path'));
                });
        }
 
@@ -146,7 +127,7 @@ export default class OpenLayersMapPart extends MapPart {
                select.on('select', function(e) {
                        if (e.selected.length > 0) {
                                let feature = e.selected[0];
-                               mapPart.callbacks['onFeatureSelected'](feature.get('path'));
+                               mapPart.callbacks['onFeatureSelected'](feature.get('cr:path'));
                        }
                });
        }
@@ -190,7 +171,7 @@ export default class OpenLayersMapPart extends MapPart {
                                return;
                        }
                        const coordinate = e.coordinate;
-                       const path = selected.get('path');
+                       const path = selected.get('cr:path');
                        if (path === null)
                                return true;
                        const res = mapPart.callbacks['onFeaturePopup'](path);
@@ -203,6 +184,44 @@ export default class OpenLayersMapPart extends MapPart {
                });
        }
 
+       selectFeatures(layerName, featureIds) {
+               // we cannot use 'this' in the function provided to OpenLayers
+               let mapPart = this;
+               this.select.getFeatures().clear();
+               const layer = this.getLayerByName(layerName);
+               const source = layer.getSource();
+               for (const featureId of featureIds) {
+                       let feature = source.getFeatureById(featureId);
+                       if (feature === null) {
+                               source.on('featuresloadend', function(e) {
+                                       feature = source.getFeatureById(featureId);
+                                       if (feature !== null)
+                                               mapPart.select.getFeatures().push(feature);
+                               });
+                       } else {
+                               this.select.getFeatures().push(feature);
+                       }
+               }
+       }
+
+       fitToLayer(layerName) {
+               // we cannot use 'this' in the function provided to OpenLayers
+               let mapPart = this;
+               const layer = this.getLayerByName(layerName);
+               const source = layer.getSource();
+               const extent = source.getExtent();
+               const options = {
+                       duration: 1000,
+                       padding: [20, 20, 20, 20],
+                       easing: easeOut,
+               };
+               if (!isEmpty(extent))
+                       this.#map.getView().fit(source.getExtent(), options);
+               source.on('featuresloadend', function(e) {
+                       mapPart.getMap().getView().fit(source.getExtent(), options);
+               });
+       }
+
        //
        // HTML
        //
@@ -210,6 +229,7 @@ export default class OpenLayersMapPart extends MapPart {
                return 'map';
        }
 
+
        //
        // STATIC FOR EXTENSION
        //