Tile-Server: Vektor-Basemap in PWA integrieren (protomaps-leaflet, Feature-Flag)
- ui.js Map.create: Basemap-Swap OSM-Raster→PMTiles-Vektorlayer hinter Flag 'by_vector_map' (?vectormap=1/0). Leaflet+markercluster+Marker unverändert, sauberer Raster-Fallback bei Fehler. Attribution Pflicht eingeblendet. - map-vector.js: protomaps-leaflet paintRules/labelRules für OpenMapTiles-Schema (Light+Dark), Labels per Canvas-Text → keine Glyphs nötig. Quelle /tiles/dach.pmtiles. - protomaps-leaflet 4.0.1 vendored. - Makefile: 'make tiles' (download→merge -H+time-filter dedup→planetiler) + 'make tiles-deploy' (atomarer Swap, ENV=prod für Produktion).
This commit is contained in:
parent
a561759034
commit
2b5afcf0ae
4 changed files with 205 additions and 6 deletions
92
backend/static/js/map-vector.js
Normal file
92
backend/static/js/map-vector.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// Vektor-Basemap für Leaflet via protomaps-leaflet, gerendert aus unseren eigenen
|
||||
// PMTiles (OpenMapTiles-Schema von planetiler, ausgeliefert unter /tiles/).
|
||||
// Ersetzt den OSM-Raster-Layer — Leaflet + markercluster + alle Marker bleiben unberührt.
|
||||
// Labels werden von protomaps-leaflet per Canvas-Text gezeichnet → KEINE Glyphs nötig.
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
// Single-File-Tile-Archiv (DACH). Liegt im data-Volume, per Range ausgeliefert.
|
||||
var TILES_FILE = 'dach.pmtiles';
|
||||
|
||||
function tilesUrl() {
|
||||
return window.location.origin + '/tiles/' + TILES_FILE;
|
||||
}
|
||||
|
||||
// Straßenbreite zoomabhängig (dünn weit draußen, breit im Detail).
|
||||
function roadWidth(z) {
|
||||
if (z >= 16) return 4;
|
||||
if (z >= 14) return 2.5;
|
||||
if (z >= 12) return 1.5;
|
||||
if (z >= 9) return 0.8;
|
||||
return 0.4;
|
||||
}
|
||||
|
||||
// Farbpaletten Light/Dark.
|
||||
var THEMES = {
|
||||
light: {
|
||||
bg: '#f4f1ec', water: '#a0c8f0', land: '#dce8c8', park: '#c8e6b0',
|
||||
road: '#ffffff', roadCasing: '#d9cfc2', building: '#e6ddcf',
|
||||
buildingLine: '#d4cabb', boundary: '#b08ac0',
|
||||
label: '#33312e', labelHalo: 'rgba(255,255,255,.85)',
|
||||
},
|
||||
dark: {
|
||||
bg: '#1a1d21', water: '#16242e', land: '#222820', park: '#27331f',
|
||||
road: '#3a4046', roadCasing: '#23282d', building: '#262b30',
|
||||
buildingLine: '#31373d', boundary: '#7d5a8c',
|
||||
label: '#cfd2d6', labelHalo: 'rgba(0,0,0,.8)',
|
||||
},
|
||||
};
|
||||
|
||||
function buildRules(t) {
|
||||
var P = protomapsL;
|
||||
var paint = [
|
||||
{ dataLayer: 'landcover',
|
||||
symbolizer: new P.PolygonSymbolizer({ fill: t.land, opacity: 0.55 }) },
|
||||
{ dataLayer: 'park',
|
||||
symbolizer: new P.PolygonSymbolizer({ fill: t.park, opacity: 0.5 }) },
|
||||
{ dataLayer: 'water',
|
||||
symbolizer: new P.PolygonSymbolizer({ fill: t.water }) },
|
||||
{ dataLayer: 'waterway',
|
||||
symbolizer: new P.LineSymbolizer({ color: t.water, width: 0.8 }) },
|
||||
// Straßen-Casing zuerst (liegt unter der Füllung), dann die Straße.
|
||||
{ dataLayer: 'transportation', minzoom: 11,
|
||||
symbolizer: new P.LineSymbolizer({ color: t.roadCasing,
|
||||
width: function (z) { return roadWidth(z) + 1.5; } }) },
|
||||
{ dataLayer: 'transportation',
|
||||
symbolizer: new P.LineSymbolizer({ color: t.road, width: roadWidth }) },
|
||||
{ dataLayer: 'building', minzoom: 13,
|
||||
symbolizer: new P.PolygonSymbolizer({ fill: t.building, stroke: t.buildingLine, width: 0.5 }) },
|
||||
{ dataLayer: 'boundary',
|
||||
symbolizer: new P.LineSymbolizer({ color: t.boundary, width: 1, dash: [2, 2] }) },
|
||||
];
|
||||
var label = [
|
||||
{ dataLayer: 'place', minzoom: 4,
|
||||
symbolizer: new P.CenteredTextSymbolizer({
|
||||
labelProps: ['name:de', 'name'],
|
||||
fill: t.label, stroke: t.labelHalo, width: 2.5,
|
||||
font: function (z) { return (z >= 10 ? '600 13px' : '600 11px') + ' system-ui, sans-serif'; },
|
||||
}) },
|
||||
];
|
||||
return { paint: paint, label: label };
|
||||
}
|
||||
|
||||
// Erzeugt den Leaflet-Layer. dark=true → dunkles Theme.
|
||||
function basemapLayer(opts) {
|
||||
opts = opts || {};
|
||||
var t = THEMES[opts.dark ? 'dark' : 'light'];
|
||||
var rules = buildRules(t);
|
||||
return protomapsL.leafletLayer({
|
||||
url: tilesUrl(),
|
||||
paintRules: rules.paint,
|
||||
labelRules: rules.label,
|
||||
backgroundColor: t.bg,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
});
|
||||
}
|
||||
|
||||
window.MapVector = {
|
||||
basemapLayer: basemapLayer,
|
||||
tilesUrl: tilesUrl,
|
||||
tilesFile: TILES_FILE,
|
||||
};
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue