forked from MapComplete/MapComplete
UI(basemap): add language support: labels now show in the selected language
This commit is contained in:
parent
4d40200d47
commit
304e15ac2b
7 changed files with 5458 additions and 45 deletions
|
@ -30,6 +30,47 @@
|
||||||
"fill-color": "#fcf7e5"
|
"fill-color": "#fcf7e5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "landcover_low_zooms",
|
||||||
|
"type": "fill",
|
||||||
|
"source": "protomaps",
|
||||||
|
"source-layer": "landcover",
|
||||||
|
"paint": {
|
||||||
|
"fill-color": [
|
||||||
|
"match",
|
||||||
|
[
|
||||||
|
"get",
|
||||||
|
"kind"
|
||||||
|
],
|
||||||
|
"grassland",
|
||||||
|
"#e5f2c9",
|
||||||
|
"barren",
|
||||||
|
"rgba(255, 243, 215, 1)",
|
||||||
|
"urban_area",
|
||||||
|
"rgba(230, 230, 230, 1)",
|
||||||
|
"farmland",
|
||||||
|
"rgba(216, 239, 210, 1)",
|
||||||
|
"glacier",
|
||||||
|
"rgba(255, 255, 255, 1)",
|
||||||
|
"scrub",
|
||||||
|
"rgba(234, 239, 210, 1)",
|
||||||
|
"#f0efdd"
|
||||||
|
],
|
||||||
|
"fill-opacity": [
|
||||||
|
"interpolate",
|
||||||
|
[
|
||||||
|
"linear"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"zoom"
|
||||||
|
],
|
||||||
|
5,
|
||||||
|
1,
|
||||||
|
7,
|
||||||
|
0
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "landuse_farmland",
|
"id": "landuse_farmland",
|
||||||
"type": "fill",
|
"type": "fill",
|
||||||
|
@ -70,16 +111,13 @@
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "landuse",
|
"source-layer": "landuse",
|
||||||
"filter": [
|
"filter": [
|
||||||
"any",
|
"in",
|
||||||
[
|
"kind",
|
||||||
"in",
|
"national_park",
|
||||||
"kind",
|
"park",
|
||||||
"national_park",
|
"cemetery",
|
||||||
"park",
|
"nature_reserve",
|
||||||
"cemetery",
|
"golf_course"
|
||||||
"nature_reserve",
|
|
||||||
"golf_course"
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
"paint": {
|
"paint": {
|
||||||
"fill-color": [
|
"fill-color": [
|
||||||
|
|
|
@ -109,15 +109,14 @@
|
||||||
"type": "fill",
|
"type": "fill",
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "landuse",
|
"source-layer": "landuse",
|
||||||
"filter":
|
"filter": [
|
||||||
[
|
"in",
|
||||||
"in",
|
"kind",
|
||||||
"kind",
|
"national_park",
|
||||||
"national_park",
|
"park",
|
||||||
"park",
|
"cemetery",
|
||||||
"cemetery",
|
"nature_reserve",
|
||||||
"nature_reserve",
|
"golf_course"
|
||||||
"golf_course"
|
|
||||||
],
|
],
|
||||||
"paint": {
|
"paint": {
|
||||||
"fill-color": [
|
"fill-color": [
|
||||||
|
@ -3010,19 +3009,16 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "physical_line_waterway_label",
|
"id": "water_waterway_label",
|
||||||
"type": "symbol",
|
"type": "symbol",
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "physical_line",
|
"source-layer": "water",
|
||||||
"minzoom": 13,
|
"minzoom": 13,
|
||||||
"filter": [
|
"filter": [
|
||||||
"all",
|
"in",
|
||||||
[
|
"kind",
|
||||||
"in",
|
"river",
|
||||||
"kind",
|
"stream"
|
||||||
"river",
|
|
||||||
"stream"
|
|
||||||
]
|
|
||||||
],
|
],
|
||||||
"layout": {
|
"layout": {
|
||||||
"symbol-placement": "line",
|
"symbol-placement": "line",
|
||||||
|
@ -3120,10 +3116,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pois_ocean",
|
"id": "water_label_ocean",
|
||||||
"type": "symbol",
|
"type": "symbol",
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "pois",
|
"source-layer": "water",
|
||||||
"filter": [
|
"filter": [
|
||||||
"any",
|
"any",
|
||||||
[
|
[
|
||||||
|
@ -3168,7 +3164,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pois_lakes",
|
"id": "water_label_lakes",
|
||||||
"type": "symbol",
|
"type": "symbol",
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "water",
|
"source-layer": "water",
|
||||||
|
@ -3313,7 +3309,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "pois_important",
|
"id": "pois",
|
||||||
"type": "symbol",
|
"type": "symbol",
|
||||||
"source": "protomaps",
|
"source": "protomaps",
|
||||||
"source-layer": "pois",
|
"source-layer": "pois",
|
||||||
|
|
|
@ -7,11 +7,11 @@ import { ExportableMap, KeyNavigationEvent, MapProperties } from "../../Models/M
|
||||||
import SvelteUIElement from "../Base/SvelteUIElement"
|
import SvelteUIElement from "../Base/SvelteUIElement"
|
||||||
import MaplibreMap from "./MaplibreMap.svelte"
|
import MaplibreMap from "./MaplibreMap.svelte"
|
||||||
import * as htmltoimage from "html-to-image"
|
import * as htmltoimage from "html-to-image"
|
||||||
import RasterLayerHandler from "./RasterLayerHandler"
|
|
||||||
import Constants from "../../Models/Constants"
|
import Constants from "../../Models/Constants"
|
||||||
import { Protocol } from "pmtiles"
|
import { Protocol } from "pmtiles"
|
||||||
import { GeoOperations } from "../../Logic/GeoOperations"
|
import { GeoOperations } from "../../Logic/GeoOperations"
|
||||||
import { Feature, LineString } from "geojson"
|
import { Feature, LineString } from "geojson"
|
||||||
|
import RasterLayerHandler from "./RasterLayerHandler"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The 'MapLibreAdaptor' bridges 'MapLibre' with the various properties of the `MapProperties`
|
* The 'MapLibreAdaptor' bridges 'MapLibre' with the various properties of the `MapProperties`
|
||||||
|
|
|
@ -66,7 +66,6 @@
|
||||||
_map.resize()
|
_map.resize()
|
||||||
const canvas = _map.getCanvas()
|
const canvas = _map.getCanvas()
|
||||||
canvas.addEventListener("webglcontextlost", (e) => {
|
canvas.addEventListener("webglcontextlost", (e) => {
|
||||||
console.warn("A MapLibreMap lost their context. Recovery is", autorecovery, e)
|
|
||||||
try {
|
try {
|
||||||
_map?.remove()
|
_map?.remove()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
5350
src/UI/Map/ProtomapsLanguageSupport.ts
Normal file
5350
src/UI/Map/ProtomapsLanguageSupport.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -4,9 +4,12 @@ import { RasterLayerPolygon } from "../../Models/RasterLayers"
|
||||||
import { RasterLayerProperties } from "../../Models/RasterLayerProperties"
|
import { RasterLayerProperties } from "../../Models/RasterLayerProperties"
|
||||||
import { Utils } from "../../Utils"
|
import { Utils } from "../../Utils"
|
||||||
import { VectorSourceSpecification } from "@maplibre/maplibre-gl-style-spec"
|
import { VectorSourceSpecification } from "@maplibre/maplibre-gl-style-spec"
|
||||||
|
import { ProtomapsLanguageSupport } from "./ProtomapsLanguageSupport"
|
||||||
|
|
||||||
class SingleBackgroundHandler {
|
class SingleBackgroundHandler {
|
||||||
// Value between 0 and 1.0
|
/**
|
||||||
|
* Current opacity of this layer, Value between 0 and 1.0
|
||||||
|
* */
|
||||||
public opacity = new UIEventSource<number>(0.0)
|
public opacity = new UIEventSource<number>(0.0)
|
||||||
private _map: Store<MLMap>
|
private _map: Store<MLMap>
|
||||||
private _background: UIEventSource<RasterLayerPolygon | undefined>
|
private _background: UIEventSource<RasterLayerPolygon | undefined>
|
||||||
|
@ -18,15 +21,18 @@ class SingleBackgroundHandler {
|
||||||
*/
|
*/
|
||||||
public static readonly DEACTIVATE_AFTER = 60
|
public static readonly DEACTIVATE_AFTER = 60
|
||||||
private fadeStep = 0.1
|
private fadeStep = 0.1
|
||||||
|
private _languageSupport: ProtomapsLanguageSupport
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
map: Store<MLMap>,
|
map: Store<MLMap>,
|
||||||
targetLayer: RasterLayerPolygon,
|
targetLayer: RasterLayerPolygon,
|
||||||
background: UIEventSource<RasterLayerPolygon | undefined>
|
background: UIEventSource<RasterLayerPolygon | undefined>,
|
||||||
|
languageSupport: ProtomapsLanguageSupport
|
||||||
) {
|
) {
|
||||||
this._targetLayer = targetLayer
|
this._targetLayer = targetLayer
|
||||||
this._map = map
|
this._map = map
|
||||||
this._background = background
|
this._background = background
|
||||||
|
this._languageSupport = languageSupport
|
||||||
|
|
||||||
background.addCallback(async () => {
|
background.addCallback(async () => {
|
||||||
await this.update()
|
await this.update()
|
||||||
|
@ -64,7 +70,7 @@ class SingleBackgroundHandler {
|
||||||
map.removeLayer(<string>this._targetLayer.properties.id)
|
map.removeLayer(<string>this._targetLayer.properties.id)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("Could not (try to) remove the raster layer", e)
|
// Probably already removed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,7 +101,7 @@ class SingleBackgroundHandler {
|
||||||
private async enable() {
|
private async enable() {
|
||||||
let ttl = 15
|
let ttl = 15
|
||||||
await this.awaitStyleIsLoaded()
|
await this.awaitStyleIsLoaded()
|
||||||
while (!this.tryEnable() && ttl > 0) {
|
while (this._background.data.properties.id === this._targetLayer.properties.id && !this.tryEnable() && ttl > 0) {
|
||||||
ttl--
|
ttl--
|
||||||
await Utils.waitFor(250)
|
await Utils.waitFor(250)
|
||||||
}
|
}
|
||||||
|
@ -137,6 +143,11 @@ class SingleBackgroundHandler {
|
||||||
if (background.type === "vector") {
|
if (background.type === "vector") {
|
||||||
const styleToSet = background.style ?? background.url
|
const styleToSet = background.style ?? background.url
|
||||||
map.setStyle(styleToSet)
|
map.setStyle(styleToSet)
|
||||||
|
this.awaitStyleIsLoaded().then(() => {
|
||||||
|
console.log("UPDATING")
|
||||||
|
this._languageSupport.update()
|
||||||
|
})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
map.addLayer(
|
map.addLayer(
|
||||||
{
|
{
|
||||||
|
@ -150,6 +161,9 @@ class SingleBackgroundHandler {
|
||||||
addLayerBeforeId
|
addLayerBeforeId
|
||||||
)
|
)
|
||||||
this.opacity.addCallbackAndRun((o) => {
|
this.opacity.addCallbackAndRun((o) => {
|
||||||
|
if (map.getStyle() === undefined || map.getLayer(background.id) === undefined) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
map.setPaintProperty(background.id, "raster-opacity", o)
|
map.setPaintProperty(background.id, "raster-opacity", o)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -166,27 +180,43 @@ class SingleBackgroundHandler {
|
||||||
Stores.Chronic(
|
Stores.Chronic(
|
||||||
8,
|
8,
|
||||||
() => this.opacity.data > 0 && this._deactivationTime !== undefined
|
() => this.opacity.data > 0 && this._deactivationTime !== undefined
|
||||||
).addCallback(() => this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep)))
|
).addCallback(() => {
|
||||||
|
try {
|
||||||
|
this.opacity.setData(Math.max(0, this.opacity.data - this.fadeStep))
|
||||||
|
} catch (e) {
|
||||||
|
// The layer probably got pruned; we just unregister
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fadeIn() {
|
private fadeIn() {
|
||||||
Stores.Chronic(
|
Stores.Chronic(
|
||||||
8,
|
8,
|
||||||
() => this.opacity.data < 1.0 && this._deactivationTime === undefined
|
() => this.opacity.data < 1.0 && this._deactivationTime === undefined
|
||||||
).addCallback(() => this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep)))
|
).addCallback(() => {
|
||||||
|
try {
|
||||||
|
this.opacity.setData(Math.min(1.0, this.opacity.data + this.fadeStep))
|
||||||
|
} catch (e) {
|
||||||
|
// The layer probably got pruned; we just unregister
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class RasterLayerHandler {
|
export default class RasterLayerHandler {
|
||||||
private _singleLayerHandlers: Record<string, SingleBackgroundHandler> = {}
|
private _singleLayerHandlers: Record<string, SingleBackgroundHandler> = {}
|
||||||
|
private _languageSupport: ProtomapsLanguageSupport
|
||||||
|
|
||||||
constructor(map: Store<MLMap>, background: UIEventSource<RasterLayerPolygon | undefined>) {
|
constructor(map: Store<MLMap>, background: UIEventSource<RasterLayerPolygon | undefined>) {
|
||||||
background.addCallbackAndRunD((l) => {
|
background.addCallbackAndRunD((l) => {
|
||||||
const key = l.properties.id
|
const key = l.properties.id
|
||||||
if (!this._singleLayerHandlers[key]) {
|
if (!this._singleLayerHandlers[key]) {
|
||||||
this._singleLayerHandlers[key] = new SingleBackgroundHandler(map, l, background)
|
this._singleLayerHandlers[key] = new SingleBackgroundHandler(map, l, background, this._languageSupport)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
this._languageSupport = new ProtomapsLanguageSupport(map)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static prepareSource(
|
public static prepareSource(
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "pmtiles://https://api.protomaps.com/tiles/v4.json?key=2af8b969a9e8b692",
|
"url": "pmtiles://https://api.protomaps.com/tiles/v4.json?key=2af8b969a9e8b692",
|
||||||
"style": "https://api.protomaps.com/styles/v5/white.json?key=2af8b969a9e8b692",
|
"style": "https://api.protomaps.com/styles/v5/white/en.json?key=2af8b969a9e8b692",
|
||||||
"connect-src": [
|
"connect-src": [
|
||||||
"https://protomaps.github.io"
|
"https://protomaps.github.io"
|
||||||
],
|
],
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
"connect-src": [
|
"connect-src": [
|
||||||
"https://protomaps.github.io"
|
"https://protomaps.github.io"
|
||||||
],
|
],
|
||||||
"style": "https://api.protomaps.com/styles/v5/grayscale.json?key=2af8b969a9e8b692",
|
"style": "https://api.protomaps.com/styles/v5/grayscale/en.json?key=2af8b969a9e8b692",
|
||||||
"id": "protomaps.grayscale",
|
"id": "protomaps.grayscale",
|
||||||
"name": "Protomaps Grayscale",
|
"name": "Protomaps Grayscale",
|
||||||
"type": "vector",
|
"type": "vector",
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
"connect-src": [
|
"connect-src": [
|
||||||
"https://protomaps.github.io"
|
"https://protomaps.github.io"
|
||||||
],
|
],
|
||||||
"style": "https://api.protomaps.com/styles/v5/dark.json?key=2af8b969a9e8b692",
|
"style": "https://api.protomaps.com/styles/v5/dark/en.json?key=2af8b969a9e8b692",
|
||||||
"id": "protomaps.dark",
|
"id": "protomaps.dark",
|
||||||
"name": "Protomaps Dark",
|
"name": "Protomaps Dark",
|
||||||
"type": "vector",
|
"type": "vector",
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "pmtiles://https://api.protomaps.com/tiles/v4.json?key=2af8b969a9e8b692",
|
"url": "pmtiles://https://api.protomaps.com/tiles/v4.json?key=2af8b969a9e8b692",
|
||||||
"style": "https://api.protomaps.com/styles/v5/black.json?key=2af8b969a9e8b692",
|
"style": "https://api.protomaps.com/styles/v5/black/en.json?key=2af8b969a9e8b692",
|
||||||
"connect-src": [
|
"connect-src": [
|
||||||
"https://protomaps.github.io"
|
"https://protomaps.github.io"
|
||||||
],
|
],
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue