3 Commits

Author SHA1 Message Date
vcoppe fcfaf043c4 fix map localization 2026-05-26 06:28:32 +02:00
vcoppe 0393a330a6 fix loading initial style 2026-05-26 06:18:00 +02:00
vcoppe 2fdb58bc7d switch contour lines based on units 2026-05-25 16:50:28 +02:00
3 changed files with 178 additions and 78 deletions
+12 -2
View File
@@ -1698,7 +1698,12 @@
"layout": { "layout": {
"icon-image": "mountain_11", "icon-image": "mountain_11",
"text-anchor": "top", "text-anchor": "top",
"text-field": ["get", "name"], "text-field": [
"case",
["has", "name:nonlatin"],
["concat", ["get", "name:latin"], " ", ["get", "name:nonlatin"]],
["coalesce", ["get", "name_en"], ["get", "name"]]
],
"text-font": ["Noto Sans Regular"], "text-font": ["Noto Sans Regular"],
"text-max-width": 9, "text-max-width": 9,
"text-offset": [0, 0.6], "text-offset": [0, 0.6],
@@ -1727,7 +1732,12 @@
"layout": { "layout": {
"icon-image": "attraction_11", "icon-image": "attraction_11",
"text-anchor": "top", "text-anchor": "top",
"text-field": ["get", "name"], "text-field": [
"case",
["has", "name:nonlatin"],
["concat", ["get", "name:latin"], " ", ["get", "name:nonlatin"]],
["coalesce", ["get", "name_en"], ["get", "name"]]
],
"text-font": ["Noto Sans Regular"], "text-font": ["Noto Sans Regular"],
"text-max-width": 9, "text-max-width": 9,
"text-offset": [0, 0.6], "text-offset": [0, 0.6],
+144 -66
View File
@@ -16,6 +16,12 @@
"tiles": ["http://localhost:8080/contours_m/{z}/{x}/{y}.mvt"], "tiles": ["http://localhost:8080/contours_m/{z}/{x}/{y}.mvt"],
"minzoom": 4, "minzoom": 4,
"maxzoom": 12 "maxzoom": 12
},
"contours_ft": {
"type": "vector",
"tiles": ["http://localhost:8080/contours_ft/{z}/{x}/{y}.mvt"],
"minzoom": 4,
"maxzoom": 12
} }
}, },
"sprite": "https://tiles.openfreemap.org/sprites/ofm_f384/ofm", "sprite": "https://tiles.openfreemap.org/sprites/ofm_f384/ofm",
@@ -117,48 +123,82 @@
} }
}, },
{ {
"id": "hillshading", "id": "hillshading",
"type": "fill", "type": "fill",
"source": "hillshading", "source": "hillshading",
"source-layer": "hillshading", "source-layer": "hillshading",
"paint": { "paint": {
"fill-color": "#bdbdbd", "fill-color": "#bdbdbd",
"fill-opacity": 0.2 "fill-opacity": 0.2
} }
}, },
{ {
"id": "contours_index_m", "id": "contours_index_m",
"type": "line", "type": "line",
"source": "contours_m", "source": "contours_m",
"source-layer": "contours_m", "source-layer": "contours_m",
"filter": [ "filter": [
"any", "any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 500], 0]], ["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 500], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 250], 0]], ["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 250], 0]],
["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 100], 0]] ["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 100], 0]]
], ],
"paint": { "paint": {
"line-color": "rgb(124, 122, 121)", "line-color": "rgb(124, 122, 121)",
"line-opacity": 0.1, "line-opacity": 0.1,
"line-width": 1.0 "line-width": 1.0
} }
}, },
{ {
"id": "contours_m", "id": "contours_m",
"type": "line", "type": "line",
"source": "contours_m", "source": "contours_m",
"source-layer": "contours_m", "source-layer": "contours_m",
"filter": [ "filter": [
"any", "any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 100], 0]], ["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 100], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 50], 0]], ["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 50], 0]],
["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 25], 0]] ["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 25], 0]]
], ],
"paint": { "paint": {
"line-color": "rgb(126, 124, 121)", "line-color": "rgb(126, 124, 121)",
"line-opacity": 0.3, "line-opacity": 0.3,
"line-width": 0.5 "line-width": 0.5
} }
},
{
"id": "contours_index_ft",
"type": "line",
"source": "contours_ft",
"source-layer": "contours_ft",
"filter": [
"any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 2000], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 800], 0]],
["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 400], 0]]
],
"paint": {
"line-color": "rgb(124, 122, 121)",
"line-opacity": 0.1,
"line-width": 1.0
}
},
{
"id": "contours_ft",
"type": "line",
"source": "contours_ft",
"source-layer": "contours_ft",
"filter": [
"any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 400], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 200], 0]],
["all", [">=", ["zoom"], 13], ["==", ["%", ["get", "ele"], 100], 0]]
],
"paint": {
"line-color": "rgb(126, 124, 121)",
"line-opacity": 0.3,
"line-width": 0.5
}
}, },
{ {
"id": "landuse_pitch", "id": "landuse_pitch",
@@ -2243,32 +2283,60 @@
} }
}, },
{ {
"id": "contours_label_m", "id": "contours_label_m",
"type": "symbol", "type": "symbol",
"source": "contours_m", "source": "contours_m",
"source-layer": "contours_m", "source-layer": "contours_m",
"filter": [ "filter": [
"any", "any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 500], 0]], ["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 500], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 250], 0]], ["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 250], 0]],
["all", ["==", ["zoom"], 13], ["==", ["%", ["get", "ele"], 100], 0]], ["all", ["==", ["zoom"], 13], ["==", ["%", ["get", "ele"], 100], 0]],
["all", [">=", ["zoom"], 14], ["==", ["%", ["get", "ele"], 50], 0]] ["all", [">=", ["zoom"], 14], ["==", ["%", ["get", "ele"], 50], 0]]
], ],
"layout": { "layout": {
"text-size": ["interpolate", ["linear"], ["zoom"], 11, 6, 18, 10], "text-size": ["interpolate", ["linear"], ["zoom"], 11, 6, 18, 10],
"text-allow-overlap": false, "text-allow-overlap": false,
"symbol-avoid-edges": true, "symbol-avoid-edges": true,
"text-ignore-placement": false, "text-ignore-placement": false,
"symbol-placement": "line", "symbol-placement": "line",
"text-rotation-alignment": "map", "text-rotation-alignment": "map",
"text-field": "{ele}m", "text-field": "{ele}m",
"text-padding": 0 "text-padding": 0
}, },
"paint": { "paint": {
"text-color": "#5c5c5c", "text-color": "#5c5c5c",
"text-halo-color": "rgba(255,255,255,0.85)", "text-halo-color": "rgba(255,255,255,0.85)",
"text-halo-width": 1.25 "text-halo-width": 1.25
} }
},
{
"id": "contours_label_ft",
"type": "symbol",
"source": "contours_ft",
"source-layer": "contours_ft",
"filter": [
"any",
["all", ["<=", ["zoom"], 11], ["==", ["%", ["get", "ele"], 2000], 0]],
["all", ["==", ["zoom"], 12], ["==", ["%", ["get", "ele"], 1000], 0]],
["all", ["==", ["zoom"], 13], ["==", ["%", ["get", "ele"], 400], 0]],
["all", [">=", ["zoom"], 14], ["==", ["%", ["get", "ele"], 200], 0]]
],
"layout": {
"text-size": ["interpolate", ["linear"], ["zoom"], 11, 6, 18, 10],
"text-allow-overlap": false,
"symbol-avoid-edges": true,
"text-ignore-placement": false,
"symbol-placement": "line",
"text-rotation-alignment": "map",
"text-field": "{ele}ft",
"text-padding": 0
},
"paint": {
"text-color": "#5c5c5c",
"text-halo-color": "rgba(255,255,255,0.85)",
"text-halo-width": 1.25
}
}, },
{ {
"id": "waterway_line_label", "id": "waterway_line_label",
@@ -2563,7 +2631,12 @@
"layout": { "layout": {
"icon-image": "mountain_11", "icon-image": "mountain_11",
"text-anchor": "top", "text-anchor": "top",
"text-field": ["get", "name"], "text-field": [
"case",
["has", "name:nonlatin"],
["concat", ["get", "name:latin"], " ", ["get", "name:nonlatin"]],
["coalesce", ["get", "name_en"], ["get", "name"]]
],
"text-font": ["Noto Sans Regular"], "text-font": ["Noto Sans Regular"],
"text-max-width": 9, "text-max-width": 9,
"text-offset": [0, 0.6], "text-offset": [0, 0.6],
@@ -2592,7 +2665,12 @@
"layout": { "layout": {
"icon-image": "attraction_11", "icon-image": "attraction_11",
"text-anchor": "top", "text-anchor": "top",
"text-field": ["get", "name"], "text-field": [
"case",
["has", "name:nonlatin"],
["concat", ["get", "name:latin"], " ", ["get", "name:nonlatin"]],
["coalesce", ["get", "name_en"], ["get", "name"]]
],
"text-font": ["Noto Sans Regular"], "text-font": ["Noto Sans Regular"],
"text-max-width": 9, "text-max-width": 9,
"text-offset": [0, 0.6], "text-offset": [0, 0.6],
+22 -10
View File
@@ -10,7 +10,8 @@ import {
import { getLayers } from '$lib/components/map/layer-control/utils'; import { getLayers } from '$lib/components/map/layer-control/utils';
import { i18n } from '$lib/i18n.svelte'; import { i18n } from '$lib/i18n.svelte';
const { currentBasemap, currentOverlays, customLayers, opacities, terrainSource } = settings; const { currentBasemap, currentOverlays, customLayers, opacities, terrainSource, distanceUnits } =
settings;
const emptySource: maplibregl.GeoJSONSourceSpecification = { const emptySource: maplibregl.GeoJSONSourceSpecification = {
type: 'geojson', type: 'geojson',
@@ -57,15 +58,21 @@ export class StyleManager {
opacities.subscribe(() => this.updateOverlays()); opacities.subscribe(() => this.updateOverlays());
terrainSource.subscribe(() => this.updateTerrain()); terrainSource.subscribe(() => this.updateTerrain());
customLayers.subscribe(() => this.updateBasemap()); customLayers.subscribe(() => this.updateBasemap());
distanceUnits.subscribe(() => {
if (get(currentBasemap) === 'topo') this.updateBasemap();
});
} }
updateBasemap() { updateBasemap() {
const map_ = get(this._map); const map_ = get(this._map);
if (!map_) return; if (!map_) return;
this.buildStyle().then((style) => map_.setStyle(style)); let basemap = get(currentBasemap);
this.buildStyle(basemap).then((style) => {
if (get(currentBasemap) === basemap) map_.setStyle(style);
});
} }
async buildStyle(): Promise<maplibregl.StyleSpecification> { async buildStyle(basemap: string): Promise<maplibregl.StyleSpecification> {
const custom = get(customLayers); const custom = get(customLayers);
const style: maplibregl.StyleSpecification = { const style: maplibregl.StyleSpecification = {
@@ -79,7 +86,6 @@ export class StyleManager {
layers: [], layers: [],
}; };
let basemap = get(currentBasemap);
const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap]; const basemapInfo = basemaps[basemap] ?? custom[basemap]?.value ?? basemaps[defaultBasemap];
let basemapStyle = basemaps.openStreetMap as maplibregl.StyleSpecification; let basemapStyle = basemaps.openStreetMap as maplibregl.StyleSpecification;
@@ -217,17 +223,23 @@ export class StyleManager {
merge(style: maplibregl.StyleSpecification, other: maplibregl.StyleSpecification) { merge(style: maplibregl.StyleSpecification, other: maplibregl.StyleSpecification) {
style.sources = { ...style.sources, ...other.sources }; style.sources = { ...style.sources, ...other.sources };
const units = get(distanceUnits);
for (let layer of other.layers ?? []) { for (let layer of other.layers ?? []) {
if ('source' in layer) {
if (layer.source == 'contours_m' && units === 'imperial') continue;
if (layer.source == 'contours_ft' && units !== 'imperial') continue;
}
if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) { if (layer.type === 'symbol' && layer.layout && layer.layout['text-field']) {
const textField = layer.layout['text-field']; const textField = layer.layout['text-field'];
if ( if (
Array.isArray(textField) && Array.isArray(textField) &&
textField.length >= 2 && textField.length == 4 &&
textField[0] === 'coalesce' && Array.isArray(textField[3]) &&
Array.isArray(textField[1]) && textField[3][0] === 'coalesce' &&
textField[1][0] === 'get' && Array.isArray(textField[3][1]) &&
typeof textField[1][1] === 'string' && textField[3][1][0] === 'get' &&
textField[1][1].startsWith('name') typeof textField[3][1][1] === 'string' &&
textField[3][1][1].startsWith('name')
) { ) {
layer.layout['text-field'] = [ layer.layout['text-field'] = [
'coalesce', 'coalesce',