forked from MapComplete/MapComplete
Themes: add possibility to enable terrain, some fixes to overlaymap and pitch control
This commit is contained in:
parent
eede2d17dd
commit
e3dec8aafa
10 changed files with 70 additions and 7 deletions
|
@ -1,2 +1,2 @@
|
|||
SPDX-FileCopyrightText: Gouvernement fran<61><6E>ais, Roulex 45
|
||||
SPDX-License-Identifier: CC0
|
||||
SPDX-License-Identifier: CC0-1.0
|
|
@ -7,6 +7,7 @@
|
|||
"en": "Everything you need to go skiing"
|
||||
},
|
||||
"icon": "./assets/layers/aerialway/chair_lift.svg",
|
||||
"enableTerrain": true,
|
||||
"layers": [
|
||||
"ski_piste",
|
||||
"aerialway",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { UIEventSource } from "../UIEventSource"
|
||||
import { ImmutableStore, Store, UIEventSource } from "../UIEventSource"
|
||||
import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig"
|
||||
import { LocalStorageSource } from "../Web/LocalStorageSource"
|
||||
import { QueryParameters } from "../Web/QueryParameters"
|
||||
|
@ -15,6 +15,7 @@ import { QueryParameters } from "../Web/QueryParameters"
|
|||
export default class InitialMapPositioning {
|
||||
public zoom: UIEventSource<number>
|
||||
public location: UIEventSource<{ lon: number; lat: number }>
|
||||
public useTerrain: Store<boolean>
|
||||
constructor(layoutToUse: LayoutConfig) {
|
||||
function localStorageSynced(
|
||||
key: string,
|
||||
|
@ -55,10 +56,11 @@ export default class InitialMapPositioning {
|
|||
)
|
||||
|
||||
this.location = new UIEventSource({ lon: lon.data, lat: lat.data })
|
||||
// Note: this syncs only in one direction
|
||||
this.location.addCallbackD((loc) => {
|
||||
lat.setData(loc.lat)
|
||||
lon.setData(loc.lon)
|
||||
})
|
||||
// Note: this syncs only in one direction
|
||||
this.useTerrain = new ImmutableStore<boolean>(layoutToUse.enableTerrain)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,6 +156,7 @@ export default class Constants {
|
|||
"addSmall",
|
||||
] as const
|
||||
public static readonly defaultPinIcons: string[] = <any>Constants._defaultPinIcons
|
||||
public static readonly maptilerApiKey = "GvoVAJgu46I5rZapJuAy"
|
||||
|
||||
private static isRetina(): boolean {
|
||||
if (Utils.runningFromConsole) {
|
||||
|
|
|
@ -18,8 +18,10 @@ export interface MapProperties {
|
|||
readonly allowMoving: UIEventSource<true | boolean>
|
||||
readonly allowRotating: UIEventSource<true | boolean>
|
||||
readonly rotation: UIEventSource<number>
|
||||
readonly pitch: UIEventSource<number>
|
||||
readonly lastClickLocation: Store<{ lon: number; lat: number }>
|
||||
readonly allowZooming: UIEventSource<true | boolean>
|
||||
readonly useTerrain: Store<boolean>
|
||||
|
||||
/**
|
||||
* Triggered when the user navigated by using the keyboard.
|
||||
|
|
|
@ -5,6 +5,7 @@ import { BBox } from "../Logic/BBox"
|
|||
import { Store, Stores } from "../Logic/UIEventSource"
|
||||
import { GeoOperations } from "../Logic/GeoOperations"
|
||||
import { RasterLayerProperties } from "./RasterLayerProperties"
|
||||
import Constants from "./Constants"
|
||||
|
||||
export class AvailableRasterLayers {
|
||||
public static EditorLayerIndex: (Feature<Polygon, EditorLayerIndexProperties> &
|
||||
|
@ -51,7 +52,7 @@ export class AvailableRasterLayers {
|
|||
type: "Feature",
|
||||
properties: {
|
||||
name: "MapTiler",
|
||||
url: "https://api.maptiler.com/maps/15cc8f61-0353-4be6-b8da-13daea5f7432/style.json?key=GvoVAJgu46I5rZapJuAy",
|
||||
url: "https://api.maptiler.com/maps/15cc8f61-0353-4be6-b8da-13daea5f7432/style.json?key="+Constants.maptilerApiKey,
|
||||
category: "osmbasedmap",
|
||||
id: "maptiler",
|
||||
type: "vector",
|
||||
|
|
|
@ -388,6 +388,18 @@ export interface LayoutConfigJson {
|
|||
*/
|
||||
enableNoteImports?: true | boolean
|
||||
|
||||
/**
|
||||
* question: Should the map use elevation data to give a 3D-feel?
|
||||
*
|
||||
* This is especially useful for hiking maps, skiing maps etc...
|
||||
*
|
||||
* funset: MapComplete default: don't use terrain
|
||||
* iftrue: Use elevation and render 3D
|
||||
* iffalse: Do not use terrain
|
||||
* group: advanced
|
||||
*/
|
||||
enableTerrain?: false | boolean
|
||||
|
||||
/**
|
||||
* question: What overpass-api instance should be used for this layout?
|
||||
*
|
||||
|
|
|
@ -61,6 +61,7 @@ export default class LayoutConfig implements LayoutInformation {
|
|||
public readonly enableShowAllQuestions: boolean
|
||||
public readonly enableExportButton: boolean
|
||||
public readonly enablePdfDownload: boolean
|
||||
public readonly enableTerrain: boolean
|
||||
|
||||
public readonly customCss?: string
|
||||
|
||||
|
@ -208,6 +209,7 @@ export default class LayoutConfig implements LayoutInformation {
|
|||
this.enableShowAllQuestions = json.enableShowAllQuestions ?? false
|
||||
this.enableExportButton = json.enableDownload ?? true
|
||||
this.enablePdfDownload = json.enablePdfDownload ?? true
|
||||
this.enableTerrain = json.enableTerrain ?? false
|
||||
this.customCss = json.customCss
|
||||
this.overpassUrl = json.overpassUrl ?? Constants.defaultOverpassUrls
|
||||
this.overpassTimeout = json.overpassTimeout ?? 30
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import { ImmutableStore, Store, UIEventSource } from "../../Logic/UIEventSource"
|
||||
import type { Map as MLMap } from "maplibre-gl"
|
||||
import { Map as MlMap, SourceSpecification } from "maplibre-gl"
|
||||
import { AvailableRasterLayers, RasterLayerPolygon } from "../../Models/RasterLayers"
|
||||
import { RasterLayerPolygon } from "../../Models/RasterLayers"
|
||||
import { Utils } from "../../Utils"
|
||||
import { BBox } from "../../Logic/BBox"
|
||||
import { ExportableMap, KeyNavigationEvent, MapProperties } from "../../Models/MapProperties"
|
||||
|
@ -10,6 +10,7 @@ import MaplibreMap from "./MaplibreMap.svelte"
|
|||
import { RasterLayerProperties } from "../../Models/RasterLayerProperties"
|
||||
import * as htmltoimage from "html-to-image"
|
||||
import RasterLayerHandler from "./RasterLayerHandler"
|
||||
import Constants from "../../Models/Constants"
|
||||
|
||||
/**
|
||||
* The 'MapLibreAdaptor' bridges 'MapLibre' with the various properties of the `MapProperties`
|
||||
|
@ -42,6 +43,8 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
readonly minzoom: UIEventSource<number>
|
||||
readonly maxzoom: UIEventSource<number>
|
||||
readonly rotation: UIEventSource<number>
|
||||
readonly pitch: UIEventSource<number>
|
||||
readonly useTerrain: Store<boolean>
|
||||
|
||||
/**
|
||||
* Functions that are called when one of those actions has happened
|
||||
|
@ -78,6 +81,8 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
this.allowZooming = state?.allowZooming ?? new UIEventSource(true)
|
||||
this.bounds = state?.bounds ?? new UIEventSource(undefined)
|
||||
this.rotation = state?.rotation ?? new UIEventSource<number>(0)
|
||||
this.pitch = state?.pitch ?? new UIEventSource<number>(0)
|
||||
this.useTerrain = state?.useTerrain ?? new ImmutableStore<boolean>(false)
|
||||
this.rasterLayer =
|
||||
state?.rasterLayer ?? new UIEventSource<RasterLayerPolygon | undefined>(undefined)
|
||||
|
||||
|
@ -108,6 +113,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
self.setMinzoom(self.minzoom.data)
|
||||
self.setMaxzoom(self.maxzoom.data)
|
||||
self.setBounds(self.bounds.data)
|
||||
self.setTerrain(self.useTerrain.data)
|
||||
rasterLayerHandler.setBackground()
|
||||
this.updateStores(true)
|
||||
})
|
||||
|
@ -121,6 +127,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
self.setMaxzoom(self.maxzoom.data)
|
||||
self.setBounds(self.bounds.data)
|
||||
self.SetRotation(self.rotation.data)
|
||||
self.setTerrain(self.useTerrain.data)
|
||||
rasterLayerHandler.setBackground()
|
||||
this.updateStores(true)
|
||||
map.on("moveend", () => this.updateStores())
|
||||
|
@ -136,6 +143,9 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
map.on("rotateend", (_) => {
|
||||
this.updateStores()
|
||||
})
|
||||
map.on("pitchend", () => {
|
||||
this.updateStores()
|
||||
})
|
||||
map.getContainer().addEventListener("keydown", (event) => {
|
||||
let locked: "islocked" = undefined
|
||||
if (!this.allowMoving.data) {
|
||||
|
@ -183,6 +193,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))
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,7 +259,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
const w = map.getContainer().getBoundingClientRect().width
|
||||
const h = map.getContainer().getBoundingClientRect().height
|
||||
|
||||
let dpi = map.getPixelRatio()
|
||||
const dpi = map.getPixelRatio()
|
||||
// The 'css'-size stays constant...
|
||||
drawOn.style.width = w + "px"
|
||||
drawOn.style.height = h + "px"
|
||||
|
@ -423,6 +434,7 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
this.bounds.setData(bbox)
|
||||
}
|
||||
this.rotation.setData(map.getBearing())
|
||||
this.pitch.setData(map.getPitch())
|
||||
}
|
||||
|
||||
private SetZoom(z: number): void {
|
||||
|
@ -579,4 +591,32 @@ export class MapLibreAdaptor implements MapProperties, ExportableMap {
|
|||
}
|
||||
map.fitBounds(bounds.toLngLat())
|
||||
}
|
||||
|
||||
private async setTerrain(useTerrain: boolean) {
|
||||
const map = this._maplibreMap.data
|
||||
if (!map) {
|
||||
return
|
||||
}
|
||||
const id = "maptiler-terrain-data"
|
||||
if (useTerrain) {
|
||||
if(map.getTerrain()){
|
||||
return
|
||||
}
|
||||
map.addSource(id, {
|
||||
"type": "raster-dem",
|
||||
"url": "https://api.maptiler.com/tiles/terrain-rgb/tiles.json?key=" + Constants.maptilerApiKey
|
||||
})
|
||||
try{
|
||||
while (!map?.isStyleLoaded()) {
|
||||
await Utils.waitFor(250)
|
||||
}
|
||||
map.setTerrain({
|
||||
source: id
|
||||
})
|
||||
}catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
let altproperties = new MapLibreAdaptor(altmap, {
|
||||
rasterLayer,
|
||||
zoom: UIEventSource.feedFrom(placedOverMapProperties.zoom),
|
||||
rotation: UIEventSource.feedFrom(placedOverMapProperties.rotation),
|
||||
pitch: UIEventSource.feedFrom(placedOverMapProperties.pitch)
|
||||
})
|
||||
altproperties.allowMoving.setData(false)
|
||||
altproperties.allowZooming.setData(false)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue