Map feature popup
[gpl/argeo-suite.git] / org.argeo.app.geo.js / src / org.argeo.app.geo.js / OpenLayersMapPart.js
index 6eff99f2ff58d8fe3635474bdc2a0e0628585fff..b2d09115f94309e890f5d31936f0b3f857d9c65a 100644 (file)
@@ -13,6 +13,7 @@ import VectorLayer from 'ol/layer/Vector.js';
 import GeoJSON from 'ol/format/GeoJSON.js';
 import GPX from 'ol/format/GPX.js';
 import Select from 'ol/interaction/Select.js';
+import Overlay from 'ol/Overlay.js';
 
 import MapPart from './MapPart.js';
 import { SentinelCloudless } from './OpenLayerTileSources.js';
@@ -79,9 +80,10 @@ export default class OpenLayersMapPart extends MapPart {
                let mapPart = this;
                this.#map.on('singleclick', function(e) {
                        let feature = null;
-                       // we chose only one
+                       // we chose the first one
                        e.map.forEachFeatureAtPixel(e.pixel, function(f) {
                                feature = f;
+                               return true;
                        });
                        if (feature !== null)
                                mapPart.callbacks['onFeatureSingleClick'](feature.get('path'));
@@ -100,4 +102,54 @@ export default class OpenLayersMapPart extends MapPart {
                        }
                });
        }
+
+       enableFeaturePopup() {
+               // we cannot use 'this' in the function provided to OpenLayers
+               let mapPart = this;
+               /**
+                * Elements that make up the popup.
+                */
+               const container = document.getElementById('popup');
+               const content = document.getElementById('popup-content');
+               const closer = document.getElementById('popup-closer');
+
+               /**
+                * Create an overlay to anchor the popup to the map.
+                */
+               const overlay = new Overlay({
+                       element: container,
+                       autoPan: false,
+                       autoPanAnimation: {
+                               duration: 250,
+                       },
+               });
+               this.#map.addOverlay(overlay);
+
+               let selected = null;
+               this.#map.on('pointermove', function(e) {
+                       if (selected !== null) {
+                               selected.setStyle(undefined);
+                               selected = null;
+                       }
+
+                       e.map.forEachFeatureAtPixel(e.pixel, function(f) {
+                               selected = f;
+                               return true;
+                       });
+
+                       if (selected == null) {
+                               overlay.setPosition(undefined);
+                               return;
+                       }
+                       const coordinate = e.coordinate;
+                       const path = selected.get('path');
+                       const res = mapPart.callbacks['onFeaturePopup'](path);
+                       if (res != null) {
+                               content.innerHTML = res;
+                               overlay.setPosition(coordinate);
+                       } else {
+                               overlay.setPosition(undefined);
+                       }
+               });
+       }
 }