Add controls to OpenLayers map
[gpl/argeo-suite.git] / js / src / geo / OpenLayersMapPart.js
index e1d8642c0fd99a8bd85098b1706c2e6af957cb26..160930d6b7447563b309de34030dcf808d24b00a 100644 (file)
@@ -2,50 +2,75 @@
  * @module OpenLayersMapPart
  */
 
-import Map from 'ol/Map.js';
-import View from 'ol/View.js';
-import OSM from 'ol/source/OSM.js';
-import TileLayer from 'ol/layer/Tile.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 { transformExtent } from 'ol/proj.js';
+
 import VectorLayer from 'ol/layer/Vector.js';
+import TileLayer from 'ol/layer/Tile.js';
+
+import VectorSource from 'ol/source/Vector.js';
 import GeoJSON from 'ol/format/GeoJSON.js';
 import GPX from 'ol/format/GPX.js';
+import OSM from 'ol/source/OSM.js';
+
 import Select from 'ol/interaction/Select.js';
 import Overlay from 'ol/Overlay.js';
 import { Style, Icon } from 'ol/style.js';
 
+import Map from 'ol/Map.js';
+import View from 'ol/View.js';
+import { OverviewMap, ScaleLine, defaults as defaultControls } from 'ol/control.js';
+
 import * as SLDReader from '@nieuwlandgeo/sldreader';
 
 import MapPart from './MapPart.js';
-import { SentinelCloudless } from './OpenLayerTileSources.js';
 
 /** OpenLayers implementation of MapPart. */
 export default class OpenLayersMapPart extends MapPart {
        /** The OpenLayers Map. */
        #map;
 
+       #overviewMap;
+
+       /** Styled layer descriptor */
+       #sld;
+
        /** Externally added callback functions. */
        callbacks = {};
 
        /** Constructor taking the mapName as an argument. */
        constructor(mapName) {
                super(mapName);
-               this.#map = new Map({
+               this.#overviewMap = new OverviewMap({
                        layers: [
-                               //                              new TileLayer({
-                               //                                      source: new SentinelCloudless(),
-                               //                              }),
                                new TileLayer({
                                        source: new OSM(),
-                                       opacity: 0.4,
-                                       transition: 0,
                                }),
                        ],
+               });
+               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({
+                       //                                                      projection: 'EPSG:4326',
+                       //                                                      center: [0, 0],
+                       //                                                      zoom: 2,
+                       //                                              }),
                        target: this.getMapName(),
                });
+               //this.#map.getView().set('projection', 'EPSG:4326', true);
        }
 
        /* GEOGRAPHICAL METHODS */
@@ -54,8 +79,13 @@ export default class OpenLayersMapPart extends MapPart {
                this.#map.getView().setZoom(zoom);
        }
 
-       setCenter(lng, lat) {
-               this.#map.getView().setCenter(fromLonLat([lng, lat]));
+       setCenter(lat, lon) {
+               this.#map.getView().setCenter(fromLonLat([lon, lat]));
+       }
+
+       fit(extent, options) {
+               var transformed = transformExtent(extent, 'EPSG:4326', this.#map.getView().getProjection());
+               this.#map.getView().fit(transformed, options);
        }
 
        addPoint(lng, lat, style) {
@@ -95,6 +125,28 @@ export default class OpenLayersMapPart extends MapPart {
                this.#map.addLayer(vectorLayer);
        }
 
+       addLayer(js) {
+               const func = new Function(js);
+               const layer = (func)();
+               this.#map.addLayer(layer);
+       }
+
+       getMap() {
+               return this.#map;
+       }
+
+       getLayerByName(name) {
+               let layers = this.#map.getLayers();
+               for (let i = 0; i < layers.getLength(); i++) {
+                       let layer = layers.item(i);
+                       let n = layer.get('name');
+                       if (n !== undefined) {
+                               if (name === n)
+                                       return layer;
+                       }
+               }
+               return undefined;
+       }
 
        /* CALLBACKS */
        enableFeatureSingleClick() {
@@ -198,6 +250,40 @@ export default class OpenLayersMapPart extends MapPart {
        //
        // SLD STYLING
        //
+
+       setSld(xml) {
+               this.#sld = SLDReader.Reader(xml);
+       }
+
+       /** Get a FeatureTypeStyle (https://nieuwlandgeo.github.io/SLDReader/api.html#FeatureTypeStyle).  */
+       getFeatureTypeStyle(styledLayerName, styleName) {
+               const sldLayer = SLDReader.getLayer(this.#sld, styledLayerName);
+               const style = styleName === undefined ? SLDReader.getStyle(sldLayer) : SLDReader.getStyle(sldLayer, styleName);
+               // OpenLayers can only use one definition
+               const featureTypeStyle = style.featuretypestyles[0];
+               return featureTypeStyle;
+       }
+
+       applyStyle(layerName, styledLayerName, styleName) {
+               const layer = this.getLayerByName(layerName);
+               const featureTypeStyle = this.getFeatureTypeStyle(styledLayerName, styleName);
+               const viewProjection = this.#map.getView().getProjection();
+               const olStyleFunction = SLDReader.createOlStyleFunction(featureTypeStyle, {
+                       // Use the convertResolution option to calculate a more accurate resolution.
+                       convertResolution: viewResolution => {
+                               const viewCenter = this.#map.getView().getCenter();
+                               return getPointResolution(viewProjection, viewResolution, viewCenter);
+                       },
+                       // If you use point icons with an ExternalGraphic, you have to use imageLoadCallback
+                       // to update the vector layer when an image finishes loading.
+                       // If you do not do this, the image will only be visible after next layer pan/zoom.
+                       imageLoadedCallback: () => {
+                               layer.changed();
+                       },
+               });
+               layer.setStyle(olStyleFunction);
+       }
+
        #applySLD(vectorLayer, text) {
                const sldObject = SLDReader.Reader(text);
                const sldLayer = SLDReader.getLayer(sldObject);
@@ -220,4 +306,4 @@ export default class OpenLayersMapPart extends MapPart {
                });
                vectorLayer.setStyle(olStyleFunction);
        }
-}
\ No newline at end of file
+}