From b6550e5c9441ddc11cc8d624aa094905269802bc Mon Sep 17 00:00:00 2001 From: ncastejon <castejon.nicolas@gmail.com> Date: Wed, 6 Jun 2018 13:26:07 +0200 Subject: [PATCH] Integrate WMS layer if WFS not exist. Try external lib feaflet.wms for WMS options --- webapp/.angular-cli.json | 3 +- webapp/package-lock.json | 42 ++ webapp/package.json | 2 + .../dataset-map/dataset-map.component.scss | 1 - .../dataset-map/dataset-map.component.ts | 124 +++-- .../app/geosource/models/metadata.model.ts | 2 +- webapp/src/app/geosource/services/index.ts | 4 +- .../src/app/geosource/services/map.service.ts | 17 + webapp/src/assets/leaflet.wms.js | 495 ++++++++++++++++++ webapp/src/tsconfig.app.json | 4 +- 10 files changed, 656 insertions(+), 38 deletions(-) create mode 100644 webapp/src/app/geosource/services/map.service.ts create mode 100644 webapp/src/assets/leaflet.wms.js diff --git a/webapp/.angular-cli.json b/webapp/.angular-cli.json index 0ce40adc..a0ecf192 100644 --- a/webapp/.angular-cli.json +++ b/webapp/.angular-cli.json @@ -25,7 +25,8 @@ "../node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css" ], "scripts": [ - "../node_modules/leaflet.markercluster/dist/leaflet.markercluster.js" + "../node_modules/leaflet.markercluster/dist/leaflet.markercluster.js", + "../node_modules/proj4leaflet/lib/proj4-compressed.js" ], "environmentSource": "environments/environment.ts", "environments": { diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 4b1a8049..00dd7ed8 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -325,6 +325,21 @@ "integrity": "sha512-EhNufyBoC1Kqaj+XMHGzi6mPUC8wVABOMTPE5XaSJc49LIVvXsyrV1HYMAPTUViT7E4wLUB38OdDmb+HshjGmA==", "dev": true }, + "@types/proj4": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@types/proj4/-/proj4-2.3.4.tgz", + "integrity": "sha1-84i2AgnEy3XsIaF6S0rFWnGlhVg=" + }, + "@types/proj4leaflet": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/proj4leaflet/-/proj4leaflet-1.0.5.tgz", + "integrity": "sha512-xqw5V5wk0iSjpDSN2X1tuEo6qL4QhfffaTpnHN6ISz3vnT4Z4m4aKdH1vQHlpJ6aJ0TBvcRmI8X2/Lv7t/0qOw==", + "requires": { + "@types/geojson": "7946.0.3", + "@types/leaflet": "1.2.7", + "@types/proj4": "2.3.4" + } + }, "@types/q": { "version": "0.0.32", "resolved": "https://registry.npmjs.org/@types/q/-/q-0.0.32.tgz", @@ -6943,6 +6958,11 @@ "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", "dev": true }, + "mgrs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mgrs/-/mgrs-1.0.0.tgz", + "integrity": "sha1-+5FYjnjJACVnI5XLQLJffNatGCk=" + }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", @@ -8425,6 +8445,23 @@ "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true }, + "proj4": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.4.4.tgz", + "integrity": "sha512-yo6qTpBQXnxhcPopKJeVwwOBRzUpEa3vzSFlr38f5mF4Jnfb6NOL/ePIomefWiZmPgkUblHpcwnWVMB8FS3GKw==", + "requires": { + "mgrs": "1.0.0", + "wkt-parser": "1.2.1" + } + }, + "proj4leaflet": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/proj4leaflet/-/proj4leaflet-1.0.2.tgz", + "integrity": "sha512-6GdDeUlhX/tHUiMEj80xQhlPjwrXcdfD0D5OBymY8WvxfbmZcdhNqQk7n7nFf53ue6QdP9ls9ZPjsAxnbZDTsw==", + "requires": { + "proj4": "2.4.4" + } + }, "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", @@ -12461,6 +12498,11 @@ "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", "dev": true }, + "wkt-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/wkt-parser/-/wkt-parser-1.2.1.tgz", + "integrity": "sha512-c6iNYzlbWNXwtcZ+0DMy1AOSHxVKFPR4a8EBVOgVbDSeSEnz2gpicmXSnuql1tKgS67CY+ughyjprP8pckk5jg==" + }, "wordwrap": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", diff --git a/webapp/package.json b/webapp/package.json index 742daeb7..16e52070 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -32,11 +32,13 @@ "@angular/router": "^5.2.0", "@types/leaflet": "^1.2.7", "@types/leaflet.markercluster": "^1.0.3", + "@types/proj4leaflet": "^1.0.5", "bulma": "^0.7.1", "core-js": "^2.4.1", "font-awesome": "^4.7.0", "leaflet": "^1.3.1", "leaflet.markercluster": "^1.3.0", + "proj4leaflet": "^1.0.2", "rxjs": "^5.5.6", "zone.js": "^0.8.19" }, diff --git a/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.scss b/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.scss index 64d0b1d7..4fb3c0b7 100644 --- a/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.scss +++ b/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.scss @@ -1,4 +1,3 @@ #frugalmap { height: 600px; - width: 80% } diff --git a/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts b/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts index da6cfc0b..bfa9bc44 100644 --- a/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts +++ b/webapp/src/app/geosource/components/dataset-detail/dataset-map/dataset-map.component.ts @@ -1,9 +1,12 @@ import { Component, OnInit, Input } from '@angular/core'; import * as L from 'leaflet'; import 'leaflet.markercluster'; +import 'proj4leaflet'; import { ActivatedRoute, ParamMap } from '@angular/router'; import { DatasetService } from '../../../services'; import { Metadata, Data } from '../../../models'; +import { MapService } from '../../../services/map.service'; +import * as wms from '../../../../../assets/leaflet.wms.js'; @Component({ selector: 'app-dataset-map', @@ -14,21 +17,20 @@ export class DatasetMapComponent implements OnInit { metadata: Metadata; constructor( - private _route: ActivatedRoute, - private _datasetService: DatasetService, + private route: ActivatedRoute, + private datasetService: DatasetService, + private mapService: MapService ) { } ngOnInit() { - this._route.parent.paramMap - .switchMap((params: ParamMap) => this._datasetService.getMetadataById(params.get('id'))) + this.route.parent.paramMap + .switchMap((params: ParamMap) => this.datasetService.getMetadataById(params.get('id'))) .subscribe((metadata: Metadata) => { - this._datasetService.getDataByMetadataById(metadata.dataset_index).subscribe(results => { - this.constructMap(results); - }); + this.constructMap(metadata); }); } - constructMap(results: Data[]) { + constructMap(metadata: Metadata) { // Déclaration de la carte avec les coordonnées du centre et le niveau de zoom. const attribution = 'Data Grand Lyon'; const satellite = L.tileLayer('https://openstreetmap.data.grandlyon.com/3857/tms/1.0.0/ortho2015@GoogleMapsCompatible/{z}/{x}/{-y}.png', { id: 'MapID', attribution: attribution }); @@ -56,33 +58,89 @@ export class DatasetMapComponent implements OnInit { const cluster = L.markerClusterGroup({ maxClusterRadius: 120 }); - results.forEach(element => { - console.log(element); - - switch (element.geometry.type) { - case 'Point': - const marker = L.marker([element.geometry.coordinates[1], element.geometry.coordinates[0]], { icon: myIcon }) - .bindPopup(element.properties.nom).addTo(dataGrandLyonMap); - // group.push(marker); - cluster.addLayer(marker); - break; - case 'Polygon': - // create a red polygon from an array of LatLng points - element.geometry.coordinates.forEach(coordinates => { - coordinates.forEach(coord => { - coord.reverse(); - }); - const polygon = L.polygon(coordinates, { color: 'red' }).addTo(dataGrandLyonMap); - group.push(polygon); - }); - - break; + const hasWFS = metadata.uri.filter(function (e) { return e.protocol === 'OGC:WFS'; }).length > 0; + metadata.uri.forEach(element => { + if (hasWFS && element.protocol === 'OGC:WFS') { + const options = { + 'name': element.name + }; + this.mapService.getWFS(options).subscribe(results => { + console.log(results); + if (results.features[0].geometry.type === 'Point') { + L.geoJSON(results, { + pointToLayer: function (feature, latlng) { + return L.marker(latlng, { icon: myIcon }); // The basic style + } + }).addTo(dataGrandLyonMap); + } else if (results.features[0].geometry.type === 'Polygon') { + L.geoJSON(results, { + onEachFeature: function (feature, layer) { + let popContent = ''; + for (const key in feature.properties) { + if (feature.properties.hasOwnProperty(key)) { + popContent += '<p>' + key + ': ' + feature.properties[key] + '</p>'; + } + } + layer.bindPopup(popContent); + } + }).addTo(dataGrandLyonMap); + } + }); + } else if (!hasWFS && element.protocol === 'OGC:WMS') { + const crs = new L.Proj.CRS('EPSG:4171', + '+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs '); + L.tileLayer.wms('https://download.data.grandlyon.com/wms/grandlyon?', { + crs: crs, + transparent: true, + layers: element.name, + format: 'image/png', + zIndex: 1000 + }).addTo(dataGrandLyonMap); + // source.addSubLayer(element.name); + // source.addTo(dataGrandLyonMap); } }); - dataGrandLyonMap.addLayer(cluster); - const featureGroup = L.featureGroup(group); - // zoom the map to the polygon - dataGrandLyonMap.fitBounds(featureGroup.getBounds()); + + + // results.forEach(element => { + // console.log(element); + + // switch (element.geometry.type) { + // case 'Point': + // const marker = L.marker([element.geometry.coordinates[1], element.geometry.coordinates[0]], { icon: myIcon }) + // .bindPopup(element.properties.nom).addTo(dataGrandLyonMap); + // // group.push(marker); + // cluster.addLayer(marker); + // break; + // case 'Polygon': + // // create a red polygon from an array of LatLng points + // element.geometry.coordinates.forEach(coordinates => { + // coordinates.forEach(coord => { + // coord.reverse(); + // }); + // const polygon = L.polygon(coordinates, { color: 'red' }).addTo(dataGrandLyonMap); + // group.push(polygon); + // }); + + // break; + // } + // }); + // dataGrandLyonMap.addLayer(cluster); + // const featureGroup = L.featureGroup(group); + // // zoom the map to the polygon + // dataGrandLyonMap.fitBounds(featureGroup.getBounds()); L.control.scale().addTo(dataGrandLyonMap); } + + onEachFeature(feature, layer) { + // does this feature have a property named popupContent? + console.log(feature); + console.log(layer); + if (feature.properties && feature.properties.nom) { + layer.bindPopup(feature.properties.nom); + } + if (feature.properties && feature.properties.odentifiant) { + layer.bindPopup(feature.properties.identifiant); + } + } } diff --git a/webapp/src/app/geosource/models/metadata.model.ts b/webapp/src/app/geosource/models/metadata.model.ts index 836459bd..d2a12d6b 100644 --- a/webapp/src/app/geosource/models/metadata.model.ts +++ b/webapp/src/app/geosource/models/metadata.model.ts @@ -32,7 +32,7 @@ interface IContact { export interface IMetadataUri { 'description': string; 'url': string; - 'protocol': Array<string>; + 'protocol': string; 'name': string; } diff --git a/webapp/src/app/geosource/services/index.ts b/webapp/src/app/geosource/services/index.ts index 422e7bd8..51982c44 100644 --- a/webapp/src/app/geosource/services/index.ts +++ b/webapp/src/app/geosource/services/index.ts @@ -1,9 +1,11 @@ import { DatasetService } from './dataset.service'; import { ElasticsearchService } from './elasticsearch.service'; +import { MapService } from './map.service'; export { DatasetService, ElasticsearchService }; export const GeosourceServices = [ DatasetService, - ElasticsearchService + ElasticsearchService, + MapService ]; diff --git a/webapp/src/app/geosource/services/map.service.ts b/webapp/src/app/geosource/services/map.service.ts new file mode 100644 index 00000000..1b5b5ae3 --- /dev/null +++ b/webapp/src/app/geosource/services/map.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { IfObservable } from 'rxjs/observable/IfObservable'; +import { Observable } from 'rxjs/Observable'; +import { HttpClient } from '@angular/common/http'; + +@Injectable() +export class MapService { + + constructor( + private http: HttpClient + ) {} + + getWFS(options): Observable<any> { + const url = 'https://download.data.grandlyon.com/wfs/grandlyon?SERVICE=WFS&VERSION=2.0.0&outputformat=GEOJSON&maxfeatures=30&request=GetFeature&typename=' + options.name + '&SRSNAME=urn:ogc:def:crs:EPSG::4171'; + return this.http.get(url); + } +} diff --git a/webapp/src/assets/leaflet.wms.js b/webapp/src/assets/leaflet.wms.js new file mode 100644 index 00000000..6a65d604 --- /dev/null +++ b/webapp/src/assets/leaflet.wms.js @@ -0,0 +1,495 @@ +/*! + * leaflet.wms.js + * A collection of Leaflet utilities for working with Web Mapping services. + * (c) 2014-2016, Houston Engineering, Inc. + * MIT License + */ + +(function (factory) { + // Module systems magic dance, Leaflet edition + if (typeof define === 'function' && define.amd) { + // AMD + define(['leaflet'], factory); + } else if (typeof module !== 'undefined') { + // Node/CommonJS + module.exports = factory(require('leaflet')); + } else { + // Browser globals + if (typeof this.L === 'undefined') + throw 'Leaflet must be loaded first!'; + // Namespace + this.L.WMS = this.L.wms = factory(this.L); + } +}(function (L) { + +// Module object +var wms = {}; + +// Quick shim for Object.keys() +if (!('keys' in Object)) { + Object.keys = function(obj) { + var result = []; + for (var i in obj) { + if (obj.hasOwnProperty(i)) { + result.push(i); + } + } + return result; + }; +} + +/* +* wms.Source +* The Source object manages a single WMS connection. Multiple "layers" can be +* created with the getLayer function, but a single request will be sent for +* each image update. Can be used in non-tiled "overlay" mode (default), or +* tiled mode, via an internal wms.Overlay or wms.TileLayer, respectively. +*/ +wms.Source = L.Layer.extend({ + 'options': { + 'untiled': true, + 'identify': true + }, + + 'initialize': function(url, options) { + L.setOptions(this, options); + if (this.options.tiled) { + this.options.untiled = false; + } + this._url = url; + this._subLayers = {}; + this._overlay = this.createOverlay(this.options.untiled); + }, + + 'createOverlay': function(untiled) { + // Create overlay with all options other than untiled & identify + var overlayOptions = {}; + for (var opt in this.options) { + if (opt != 'untiled' && opt != 'identify') { + overlayOptions[opt] = this.options[opt]; + } + } + if (untiled) { + return wms.overlay(this._url, overlayOptions); + } else { + return wms.tileLayer(this._url, overlayOptions); + } + }, + + 'onAdd': function() { + this.refreshOverlay(); + }, + + 'getEvents': function() { + if (this.options.identify) { + return {'click': this.identify}; + } else { + return {}; + } + }, + + 'setOpacity': function(opacity) { + this.options.opacity = opacity; + if (this._overlay) { + this._overlay.setOpacity(opacity); + } + }, + + 'bringToBack': function() { + this.options.isBack = true; + if (this._overlay) { + this._overlay.bringToBack(); + } + }, + + 'bringToFront': function() { + this.options.isBack = false; + if (this._overlay) { + this._overlay.bringToFront(); + } + }, + + 'getLayer': function(name) { + return wms.layer(this, name); + }, + + 'addSubLayer': function(name) { + this._subLayers[name] = true; + this.refreshOverlay(); + }, + + 'removeSubLayer': function(name) { + delete this._subLayers[name]; + this.refreshOverlay(); + }, + + 'refreshOverlay': function() { + var subLayers = Object.keys(this._subLayers).join(","); + if (!this._map) { + return; + } + if (!subLayers) { + this._overlay.remove(); + } else { + this._overlay.setParams({'layers': subLayers}); + this._overlay.addTo(this._map); + } + }, + + 'identify': function(evt) { + // Identify map features in response to map clicks. To customize this + // behavior, create a class extending wms.Source and override one or + // more of the following hook functions. + + var layers = this.getIdentifyLayers(); + if (!layers.length) { + return; + } + this.getFeatureInfo( + evt.containerPoint, evt.latlng, layers, + this.showFeatureInfo + ); + }, + + 'getFeatureInfo': function(point, latlng, layers, callback) { + // Request WMS GetFeatureInfo and call callback with results + // (split from identify() to faciliate use outside of map events) + var params = this.getFeatureInfoParams(point, layers), + url = this._url + L.Util.getParamString(params, this._url); + + this.showWaiting(); + this.ajax(url, done); + + function done(result) { + this.hideWaiting(); + var text = this.parseFeatureInfo(result, url); + callback.call(this, latlng, text); + } + }, + + 'ajax': function(url, callback) { + ajax.call(this, url, callback); + }, + + 'getIdentifyLayers': function() { + // Hook to determine which layers to identify + if (this.options.identifyLayers) + return this.options.identifyLayers; + return Object.keys(this._subLayers); + }, + + 'getFeatureInfoParams': function(point, layers) { + // Hook to generate parameters for WMS service GetFeatureInfo request + var wmsParams, overlay; + if (this.options.untiled) { + // Use existing overlay + wmsParams = this._overlay.wmsParams; + } else { + // Create overlay instance to leverage updateWmsParams + overlay = this.createOverlay(true); + overlay.updateWmsParams(this._map); + wmsParams = overlay.wmsParams; + wmsParams.layers = layers.join(','); + } + var infoParams = { + 'request': 'GetFeatureInfo', + 'query_layers': layers.join(','), + 'X': Math.round(point.x), + 'Y': Math.round(point.y) + }; + return L.extend({}, wmsParams, infoParams); + }, + + 'parseFeatureInfo': function(result, url) { + // Hook to handle parsing AJAX response + if (result == "error") { + // AJAX failed, possibly due to CORS issues. + // Try loading content in <iframe>. + result = "<iframe src='" + url + "' style='border:none'>"; + } + return result; + }, + + 'showFeatureInfo': function(latlng, info) { + // Hook to handle displaying parsed AJAX response to the user + if (!this._map) { + return; + } + this._map.openPopup(info, latlng); + }, + + 'showWaiting': function() { + // Hook to customize AJAX wait animation + if (!this._map) + return; + this._map._container.style.cursor = "progress"; + }, + + 'hideWaiting': function() { + // Hook to remove AJAX wait animation + if (!this._map) + return; + this._map._container.style.cursor = "default"; + } +}); + +wms.source = function(url, options) { + return new wms.Source(url, options); +}; + +/* +* Layer +* Leaflet "layer" with all actual rendering handled via an underlying Source +* object. Can be called directly with a URL to automatically create or reuse +* an existing Source. Note that the auto-source feature doesn't work well in +* multi-map environments; so for best results, create a Source first and use +* getLayer() to retrieve wms.Layer instances. +*/ + +wms.Layer = L.Layer.extend({ + 'initialize': function(source, layerName, options) { + L.setOptions(this, options); + if (!source.addSubLayer) { + // Assume source is a URL + source = wms.getSourceForUrl(source, options); + } + this._source = source; + this._name = layerName; + }, + 'onAdd': function() { + if (!this._source._map) + this._source.addTo(this._map); + this._source.addSubLayer(this._name); + }, + 'onRemove': function() { + this._source.removeSubLayer(this._name); + }, + 'setOpacity': function(opacity) { + this._source.setOpacity(opacity); + }, + 'bringToBack': function() { + this._source.bringToBack(); + }, + 'bringToFront': function() { + this._source.bringToFront(); + } +}); + +wms.layer = function(source, options) { + return new wms.Layer(source, options); +}; + +// Cache of sources for use with wms.Layer auto-source option +var sources = {}; +wms.getSourceForUrl = function(url, options) { + if (!sources[url]) { + sources[url] = wms.source(url, options); + } + return sources[url]; +}; + + +// Copy tiled WMS layer from leaflet core, in case we need to subclass it later +wms.TileLayer = L.TileLayer.WMS; +wms.tileLayer = L.tileLayer.wms; + +/* +* wms.Overlay: +* "Single Tile" WMS image overlay that updates with map changes. +* Portions of wms.Overlay are directly extracted from L.TileLayer.WMS. +* See Leaflet license. +*/ +wms.Overlay = L.Layer.extend({ + 'defaultWmsParams': { + 'service': 'WMS', + 'request': 'GetMap', + 'version': '1.3.0', + 'layers': '', + 'styles': '', + 'format': 'image/jpeg', + 'transparent': false + }, + + 'options': { + 'crs': null, + 'uppercase': false, + 'attribution': '', + 'opacity': 1, + 'isBack': false, + 'minZoom': 0, + 'maxZoom': 18 + }, + + 'initialize': function(url, options) { + this._url = url; + + // Move WMS parameters to params object + var params = {}, opts = {}; + for (var opt in options) { + if (opt in this.options) { + opts[opt] = options[opt]; + } else { + params[opt] = options[opt]; + } + } + L.setOptions(this, opts); + this.wmsParams = L.extend({}, this.defaultWmsParams, params); + }, + + 'setParams': function(params) { + L.extend(this.wmsParams, params); + this.update(); + }, + + 'getAttribution': function() { + return this.options.attribution; + }, + + 'onAdd': function() { + this.update(); + }, + + 'onRemove': function(map) { + if (this._currentOverlay) { + map.removeLayer(this._currentOverlay); + delete this._currentOverlay; + } + if (this._currentUrl) { + delete this._currentUrl; + } + }, + + 'getEvents': function() { + return { + 'moveend': this.update + }; + }, + + 'update': function() { + if (!this._map) { + return; + } + // Determine image URL and whether it has changed since last update + this.updateWmsParams(); + var url = this.getImageUrl(); + if (this._currentUrl == url) { + return; + } + this._currentUrl = url; + + // Keep current image overlay in place until new one loads + // (inspired by esri.leaflet) + var bounds = this._map.getBounds(); + var overlay = L.imageOverlay(url, bounds, {'opacity': 0}); + overlay.addTo(this._map); + overlay.once('load', _swap, this); + function _swap() { + if (!this._map) { + return; + } + if (overlay._url != this._currentUrl) { + this._map.removeLayer(overlay); + return; + } else if (this._currentOverlay) { + this._map.removeLayer(this._currentOverlay); + } + this._currentOverlay = overlay; + overlay.setOpacity( + this.options.opacity ? this.options.opacity : 1 + ); + if (this.options.isBack === true) { + overlay.bringToBack(); + } + if (this.options.isBack === false) { + overlay.bringToFront(); + } + } + if ((this._map.getZoom() < this.options.minZoom) || + (this._map.getZoom() > this.options.maxZoom)){ + this._map.removeLayer(overlay); + } + }, + + 'setOpacity': function(opacity) { + this.options.opacity = opacity; + if (this._currentOverlay) { + this._currentOverlay.setOpacity(opacity); + } + }, + + 'bringToBack': function() { + this.options.isBack = true; + if (this._currentOverlay) { + this._currentOverlay.bringToBack(); + } + }, + + 'bringToFront': function() { + this.options.isBack = false; + if (this._currentOverlay) { + this._currentOverlay.bringToFront(); + } + }, + + // See L.TileLayer.WMS: onAdd() & getTileUrl() + 'updateWmsParams': function(map) { + if (!map) { + map = this._map; + } + // Compute WMS options + var bounds = map.getBounds(); + var size = map.getSize(); + var wmsVersion = parseFloat(this.wmsParams.version); + var crs = this.options.crs || map.options.crs; + var projectionKey = wmsVersion >= 1.3 ? 'crs' : 'srs'; + var nw = crs.project(bounds.getNorthWest()); + var se = crs.project(bounds.getSouthEast()); + + // Assemble WMS parameter string + var params = { + 'width': size.x, + 'height': size.y + }; + params[projectionKey] = crs.code; + params.bbox = ( + wmsVersion >= 1.3 && crs === L.CRS.EPSG4326 ? + [se.y, nw.x, nw.y, se.x] : + [nw.x, se.y, se.x, nw.y] + ).join(','); + + L.extend(this.wmsParams, params); + }, + + 'getImageUrl': function() { + var uppercase = this.options.uppercase || false; + var pstr = L.Util.getParamString(this.wmsParams, this._url, uppercase); + return this._url + pstr; + } +}); + +wms.overlay = function(url, options) { + return new wms.Overlay(url, options); +}; + +// Simple AJAX helper (since we can't assume jQuery etc. are present) +function ajax(url, callback) { + var context = this, + request = new XMLHttpRequest(); + request.onreadystatechange = change; + request.open('GET', url); + request.send(); + + function change() { + if (request.readyState === 4) { + if (request.status === 200) { + callback.call(context, request.responseText); + } else { + callback.call(context, "error"); + } + } + } +} + +return wms; + +})); diff --git a/webapp/src/tsconfig.app.json b/webapp/src/tsconfig.app.json index 727fe0a3..edeee7ac 100644 --- a/webapp/src/tsconfig.app.json +++ b/webapp/src/tsconfig.app.json @@ -3,10 +3,12 @@ "compilerOptions": { "outDir": "../out-tsc/app", "baseUrl": "./", + "allowJs": true, "module": "es2015", "types": [ "leaflet", - "leaflet.markercluster" + "leaflet.markercluster", + "proj4leaflet" ] }, "exclude": [ -- GitLab