diff --git a/package.json b/package.json index eaa292a1c..700960e5e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mapcomplete", - "version": "0.46.5", + "version": "0.46.6", "repository": "https://github.com/pietervdvn/MapComplete", "description": "A small website to edit OSM easily", "bugs": "https://github.com/pietervdvn/MapComplete/issues", diff --git a/src/Logic/State/UserRelatedState.ts b/src/Logic/State/UserRelatedState.ts index bae3fa7d4..0087e1080 100644 --- a/src/Logic/State/UserRelatedState.ts +++ b/src/Logic/State/UserRelatedState.ts @@ -69,6 +69,8 @@ export default class UserRelatedState { "button" | "button_click_right" | "button_click" | "click" | "click_right" >("button_click_right") + public readonly showScale : UIEventSource + /** * Preferences as tags exposes many preferences and state properties as record. * This is used to bridge the internal state with the usersettings.json layerconfig file @@ -123,6 +125,7 @@ export default class UserRelatedState { documentation: "How adding a new feature is done", } ) + this.showScale = UIEventSource.asBoolean(this.osmConnection.GetPreference("preference-show-scale","false")) this.imageLicense = this.osmConnection.GetPreference("pictures-license", "CC0", { documentation: "The license under which new images are uploaded", diff --git a/src/Models/MapProperties.ts b/src/Models/MapProperties.ts index eb86c31d6..9ae66d579 100644 --- a/src/Models/MapProperties.ts +++ b/src/Models/MapProperties.ts @@ -22,6 +22,7 @@ export interface MapProperties { readonly lastClickLocation: Store<{ lon: number; lat: number }> readonly allowZooming: UIEventSource readonly useTerrain: Store + readonly showScale: UIEventSource /** * Triggered when the user navigated by using the keyboard. diff --git a/src/Models/ThemeViewState.ts b/src/Models/ThemeViewState.ts index 7b49572b2..1e2730014 100644 --- a/src/Models/ThemeViewState.ts +++ b/src/Models/ThemeViewState.ts @@ -889,6 +889,9 @@ export default class ThemeViewState implements SpecialVisualizationState { } }) }) + this.userRelatedState.showScale.addCallbackAndRun(showScale => { + this.mapProperties.showScale.set(showScale) + }) new ThemeViewStateHashActor(this) new MetaTagging(this) new TitleHandler(this.selectedElement, this.featureProperties, this) diff --git a/src/UI/Map/MapLibreAdaptor.ts b/src/UI/Map/MapLibreAdaptor.ts index f52cefaa8..f7f2fccac 100644 --- a/src/UI/Map/MapLibreAdaptor.ts +++ b/src/UI/Map/MapLibreAdaptor.ts @@ -1,5 +1,5 @@ import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource" -import maplibregl, { Map as MLMap, Map as MlMap, SourceSpecification } from "maplibre-gl" +import maplibregl, { Map as MLMap, Map as MlMap, ScaleControl, SourceSpecification } from "maplibre-gl" import { RasterLayerPolygon } from "../../Models/RasterLayers" import { Utils } from "../../Utils" import { BBox } from "../../Logic/BBox" @@ -23,13 +23,13 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { "dragRotate", "dragPan", "keyboard", - "touchZoomRotate", + "touchZoomRotate" ] private static maplibre_zoom_handlers = [ "scrollZoom", "boxZoom", "doubleClickZoom", - "touchZoomRotate", + "touchZoomRotate" ] readonly location: UIEventSource<{ lon: number; lat: number }> readonly zoom: UIEventSource @@ -47,6 +47,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { readonly rotation: UIEventSource readonly pitch: UIEventSource readonly useTerrain: Store + readonly showScale: UIEventSource private static pmtilesInited = false /** @@ -92,6 +93,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { this.useTerrain = state?.useTerrain ?? new ImmutableStore(false) this.rasterLayer = state?.rasterLayer ?? new UIEventSource(undefined) + this.showScale = state?.showScale ?? new UIEventSource(false) const lastClickLocation = new UIEventSource<{ lat: number @@ -104,6 +106,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { new RasterLayerHandler(this._maplibreMap, this.rasterLayer) const clickmodes = ["left", "middle", "right"] as const + function handleClick(e: maplibregl.MapMouseEvent, mode?: "left" | "right" | "middle") { if (e.originalEvent["consumed"]) { // Workaround, 'ShowPointLayer' sets this flag @@ -129,6 +132,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { self.setMaxzoom(self.maxzoom.data) self.setBounds(self.bounds.data) self.setTerrain(self.useTerrain.data) + self.setScale(self.showScale.data) this.updateStores(true) }) self.MoveMapToCurrentLoc(self.location.data) @@ -142,6 +146,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { self.setBounds(self.bounds.data) self.SetRotation(self.rotation.data) self.setTerrain(self.useTerrain.data) + self.setScale(self.showScale.data) this.updateStores(true) map.on("moveend", () => this.updateStores()) map.on("click", (e) => { @@ -213,6 +218,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { this.allowZooming.addCallbackAndRun((allowZooming) => self.setAllowZooming(allowZooming)) this.bounds.addCallbackAndRunD((bounds) => self.setBounds(bounds)) this.useTerrain?.addCallbackAndRun((useTerrain) => self.setTerrain(useTerrain)) + this.showScale?.addCallbackAndRun(showScale => self.setScale(showScale)) } /** @@ -227,9 +233,9 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { return { map: mlmap, ui: new SvelteUIElement(MaplibreMap, { - map: mlmap, + map: mlmap }), - mapproperties: new MapLibreAdaptor(mlmap), + mapproperties: new MapLibreAdaptor(mlmap) } } @@ -297,7 +303,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { ) { const event = { date: new Date(), - key: key, + key: key } for (let i = 0; i < this._onKeyNavigation.length; i++) { @@ -486,7 +492,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { const bounds = map.getBounds() const bbox = new BBox([ [bounds.getEast(), bounds.getNorth()], - [bounds.getWest(), bounds.getSouth()], + [bounds.getWest(), bounds.getSouth()] ]) if (this.bounds.data === undefined || !isSetup) { this.bounds.setData(bbox) @@ -664,18 +670,42 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap { type: "raster-dem", url: "https://api.maptiler.com/tiles/terrain-rgb/tiles.json?key=" + - Constants.maptilerApiKey, + Constants.maptilerApiKey }) try { while (!map?.isStyleLoaded()) { await Utils.waitFor(250) } map.setTerrain({ - source: id, + source: id }) } catch (e) { console.error(e) } } } + + private scaleControl: maplibregl.ScaleControl = undefined + + private setScale(showScale: boolean) { + const map = this._maplibreMap.data + if (!map) { + return + } + if (!showScale && this.scaleControl) { + map.removeControl(this.scaleControl) + return + } + console.log("Adding scale") + if (this.scaleControl === undefined) { + + this.scaleControl = new ScaleControl({ + maxWidth: 80, + unit: "metric" + }) + } + if (!map.hasControl(this.scaleControl)) { + map.addControl(this.scaleControl, "bottom-right") + } + } } diff --git a/src/UI/ThemeViewGUI.svelte b/src/UI/ThemeViewGUI.svelte index 92f7122b7..ab4b296d4 100644 --- a/src/UI/ThemeViewGUI.svelte +++ b/src/UI/ThemeViewGUI.svelte @@ -390,6 +390,11 @@ {/if} + +
+ +
+