nakarte

Source code of https://map.sikmir.ru (fork)
git clone git://git.sikmir.ru/nakarte
Log | Files | Refs | LICENSE

commit 34d48fb4d1a2f91270b9327e1d177ba192230ec4
parent a1c74ca3489e1fce50c1eeccd8970086656183e6
Author: Sergey Orlov <wladimirych@gmail.com>
Date:   Fri, 11 Dec 2020 22:23:02 +0100

layers: add vector overviews for local maps with limited minimal zoom

Diffstat:
Msrc/layers.js | 142+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
Asrc/lib/leaflet.layer.LayerCutlineOverview/index.js | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 166 insertions(+), 54 deletions(-)

diff --git a/src/layers.js b/src/layers.js @@ -12,6 +12,14 @@ import {RetinaTileLayer} from '~/lib/leaflet.layer.RetinaTileLayer'; import urlViaCorsProxy from '~/lib/CORSProxy'; import '~/lib/leaflet.layer.TileLayer.cutline'; import {getCutline} from '~/lib/layers-cutlines'; +import {LayerCutlineOverview} from '~/lib/leaflet.layer.LayerCutlineOverview'; + +class LayerGroupWithOptions extends L.LayerGroup { + constructor(layers, options) { + super(layers); + L.setOptions(this, options); + } +} const layersDefs = [ { @@ -867,49 +875,65 @@ import {getCutline} from '~/lib/layers-cutlines'; ) }, { - title: 'France Topo 250m (zoom ≥ 6)', + title: 'France Topo 250m', isDefault: false, - layer: L.tileLayer( - "https://wxs.ign.fr/an7nvfzojv5wa96dsga5nk8w/geoportail/wmts?" + - "layer=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN25TOUR.CV&style=normal&tilematrixset=PM&" + - "Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg&" + - "TileMatrix={z}&TileCol={x}&TileRow={y}", - { - minZoom: 6, - maxNativeZoom: 16, - bounds: [[-46.44072, -178.18694], [51.12562, 77.61086]], - code: 'Ft', - isOverlay: true, - isOverlayTransparent: false, - tms: false, - print: true, - jnx: true, - scaleDependent: false, - shortName: 'france_topo_25k', - cutline: getCutline('france'), - } - ) + layer: new LayerGroupWithOptions( + [ + L.tileLayer( + 'https://wxs.ign.fr/an7nvfzojv5wa96dsga5nk8w/geoportail/wmts?' + + 'layer=GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN25TOUR.CV&style=normal&tilematrixset=PM&' + + 'Service=WMTS&Request=GetTile&Version=1.0.0&Format=image%2Fjpeg&' + + 'TileMatrix={z}&TileCol={x}&TileRow={y}', + { + minZoom: 6, + maxNativeZoom: 16, + bounds: [ + [-46.44072, -178.18694], + [51.12562, 77.61086], + ], + isOverlay: true, + isOverlayTransparent: false, + tms: false, + print: true, + jnx: true, + scaleDependent: false, + shortName: 'france_topo_25k', + cutline: getCutline('france'), + } + ), + new LayerCutlineOverview(getCutline('france'), 5, 'France Topo 250m (zoom ≥ 6)'), + ], + {code: 'Ft', isOverlay: true} + ), }, { - title: 'Great Britain Topo (zoom ≥ 12)', + title: 'Great Britain Topo', isDefault: false, - layer: new BingLayer(config.bingKey, + layer: new LayerGroupWithOptions( + [ + new BingLayer(config.bingKey, { + type: 'OrdnanceSurvey', + minZoom: 12, + maxNativeZoom: 16, + bounds: [ + [49.83793, -7.75643], + [60.87164, 1.82356], + ], + isOverlay: true, + isOverlayTransparent: false, + scaleDependent: false, + print: true, + jnx: true, + shortName: 'england_topo', + cutline: getCutline('great_britain'), + }), + new LayerCutlineOverview(getCutline('great_britain'), 11, 'Great Britain Topo (zoom ≥ 12)'), + ], { - type: 'OrdnanceSurvey', - minZoom: 12, - maxNativeZoom: 16, - bounds: [[49.83793, -7.75643], [60.87164, 1.82356]], code: 'Gbt', isOverlay: true, - isOverlayTransparent: false, - scaleDependent: false, - print: true, - jnx: true, - shortName: 'england_topo', - cutline: getCutline('great_britain'), } ), - }, { title: 'Waymarked Cycling Trails', @@ -945,25 +969,35 @@ import {getCutline} from '~/lib/layers-cutlines'; }) }, { - title: 'Slovakia topo (zoom ≥ 10)', + title: 'Slovakia topo', description: '<a href="https://mapy.hiking.sk">https://mapy.hiking.sk/</a>', isDefault: false, - layer: L.tileLayer('https://static.mapy.hiking.sk/topo/{z}/{x}/{y}.png', + layer: new LayerGroupWithOptions( + [ + L.tileLayer('https://static.mapy.hiking.sk/topo/{z}/{x}/{y}.png', { + isOverlay: true, + tms: false, + print: true, + jnx: true, + scaleDependent: false, + shortName: 'slovakia_topo', + isOverlayTransparent: false, + maxNativeZoom: 15, + minZoom: 10, + bounds: [ + [47.5172, 16.74316], + [49.91343, 22.74837], + ], + noCors: true, + cutline: getCutline('slovakia'), + }), + new LayerCutlineOverview(getCutline('slovakia'), 9, 'Slovakia topo (zoom ≥ 10)'), + ], { code: 'St', isOverlay: true, - tms: false, - print: true, - jnx: true, - scaleDependent: false, - shortName: 'slovakia_topo', - isOverlayTransparent: false, - maxNativeZoom: 15, - minZoom: 10, - bounds: [[47.5172, 16.74316], [49.91343, 22.74837]], - noCors: true, - cutline: getCutline('slovakia'), - }), + } + ), }, { title: 'Yandex tracks (zoom ≥ 10)', @@ -1055,9 +1089,9 @@ import {getCutline} from '~/lib/layers-cutlines'; 'Topo 250m', 'Montenegro topo 250m', 'Finland Topo', - 'France Topo 250m (zoom ≥ 6)', - 'Great Britain Topo (zoom ≥ 12)', - 'Slovakia topo (zoom ≥ 10)', + 'France Topo 250m', + 'Great Britain Topo', + 'Slovakia topo', 'Spain topo', ], }, @@ -1137,21 +1171,21 @@ import {getCutline} from '~/lib/layers-cutlines'; 'Norway paper map', 'Norway topo', 'Finland Topo', - 'Slovakia topo (zoom ≥ 10)', + 'Slovakia topo', 'Spain topo', 'Mountains by Aleksey Tsvetkov', 'Slazav mountains', 'GGC 1km', 'Topo 1km', 'Caucasus 1km', - 'Great Britain Topo (zoom ≥ 12)', + 'Great Britain Topo', 'GGC 500m', 'Topo 500m', 'Caucasus 500m', 'GGC 250m', 'Topo 250m', 'Montenegro topo 250m', - 'France Topo 250m (zoom ≥ 6)', + 'France Topo 250m', 'Slazav map', 'Races', 'O-sport', diff --git a/src/lib/leaflet.layer.LayerCutlineOverview/index.js b/src/lib/leaflet.layer.LayerCutlineOverview/index.js @@ -0,0 +1,78 @@ +import L from 'leaflet'; + +class LayerCutlineOverview extends L.Layer { + options = { + style: { + stroke: true, + color: '#db5a00', + weight: 4, + opacity: 1, + fill: true, + fillOpacity: 0.2, + }, + }; + + constructor(cutline, maxOverviewZoom, text) { + super(); + this.cutline = cutline; + this.maxZoom = maxOverviewZoom; + this.text = text; + this._features = L.featureGroup(); + this._isCutlineRequested = false; + } + + onAdd() { + if (!this._isCutlineRequested) { + this._isCutlineRequested = true; + this._createFeatures().then(this._updateVisibility.bind(this)); + } + this._updateVisibility(); + this._map.on('zoomend', this._updateVisibility, this); + } + + onRemove() { + this._map.off('zoomend', this._updateVisibility, this); + this._map.removeLayer(this._features); + } + + async _createFeatures() { + let cutlinePromise = this.cutline; + if (typeof cutlinePromise === 'function') { + cutlinePromise = cutlinePromise(); + } + if (!cutlinePromise.then) { + cutlinePromise = Promise.resolve(cutlinePromise); + } + let cutlineCoords; + try { + cutlineCoords = await cutlinePromise; + } catch (_) { + // will be handled as empty later + } + if (cutlineCoords) { + for (const lineString of cutlineCoords) { + const feature = L.polygon( + lineString.map(([lon, lat]) => [lat, lon]), + this.options.style + ); + feature.bindTooltip(this.text, {sticky: true}); + feature.on('click', (e) => this._map.setView(e.latlng, this.maxZoom + 1)); + this._features.addLayer(feature); + } + } + } + + _updateVisibility() { + if (!this._map) { + return; + } + const zoom = this._map.getZoom(); + if (zoom <= this.maxZoom) { + this._map.addLayer(this._features); + } else { + this._map.removeLayer(this._features); + } + } +} + +export {LayerCutlineOverview};