From a27695d9c60d7d32646011aecda5b512bbc88cfa Mon Sep 17 00:00:00 2001 From: rene Date: Fri, 5 Jun 2026 09:24:13 +0200 Subject: [PATCH] =?UTF-8?q?MapLibre-Perf-Test:=20/maplibre-perf-test=20(Ba?= =?UTF-8?q?semap=20+=20600=20Cluster-Marker,=20GPU)=20=E2=80=94=20Handy-Pr?= =?UTF-8?q?oof=20vor=20dem=20Umbau?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/main.py | 6 +++ backend/static/js/maplibre-perf-test.js | 70 +++++++++++++++++++++++++ backend/static/maplibre-perf-test.html | 23 ++++++++ 3 files changed, 99 insertions(+) create mode 100644 backend/static/js/maplibre-perf-test.js create mode 100644 backend/static/maplibre-perf-test.html diff --git a/backend/main.py b/backend/main.py index 14622d7..328f63f 100644 --- a/backend/main.py +++ b/backend/main.py @@ -441,6 +441,12 @@ async def ui_vector_test(): # Testet den echten ui.js-Vektor-Pfad (UI.map.create) ohne Auth/App-Shell. return FileResponse(os.path.join(STATIC_DIR, "ui-vector-test.html"), media_type="text/html") + +@app.get("/maplibre-perf-test") +async def maplibre_perf_test(): + # Wegwerf-Perf-Test: MapLibre GPU + 600 Cluster-Marker auf DACH-Basemap (Handy-Test). + return FileResponse(os.path.join(STATIC_DIR, "maplibre-perf-test.html"), media_type="text/html") + # User-generierte Medien (Fotos aus Tagebuch, Giftköder-Alarm, etc.) MEDIA_DIR = os.getenv("MEDIA_DIR", "/data/media") os.makedirs(MEDIA_DIR, exist_ok=True) diff --git a/backend/static/js/maplibre-perf-test.js b/backend/static/js/maplibre-perf-test.js new file mode 100644 index 0000000..7c03d4b --- /dev/null +++ b/backend/static/js/maplibre-perf-test.js @@ -0,0 +1,70 @@ +// Wegwerf-Perf-Test: beweist MapLibre-GPU-Rendering auf dem Handy mit realistischer +// Marker-Last (600 Punkte, GeoJSON-Clustering) auf unserer DACH-Basemap — die Kombi, +// die mit protomaps-leaflet (Main-Thread) den UI-Thread blockierte. +// Cluster-Zahlen weggelassen (Text bräuchte Glyphs → kommt erst in M3). +(function () { + 'use strict'; + var st = document.getElementById('status'); + function set(t) { if (st) st.textContent = t; } + + try { + var proto = new pmtiles.Protocol(); + maplibregl.addProtocol('pmtiles', proto.tile); + var isDark = document.documentElement.dataset.theme === 'dark'; + + var map = new maplibregl.Map({ + container: 'map', + style: MapGLStyle.build({ dark: isDark }), + center: [11.576, 48.137], zoom: 12, hash: true, + }); + map.addControl(new maplibregl.NavigationControl(), 'top-right'); + map.addControl(new maplibregl.ScaleControl()); + + // Kategorie-Icon (farbiger Kreis) per Canvas → addImage (Icons brauchen KEINE Glyphs). + function makeIcon(color) { + var s = 34, c = document.createElement('canvas'); c.width = c.height = s; + var x = c.getContext('2d'); + x.beginPath(); x.arc(s / 2, s / 2, s / 2 - 3, 0, Math.PI * 2); + x.fillStyle = color; x.fill(); + x.lineWidth = 2; x.strokeStyle = 'rgba(52,68,36,0.6)'; x.stroke(); + return x.getImageData(0, 0, s, s); + } + + // 600 deterministische Pseudo-POIs um München (3 Kategorien). + function genPois(n) { + var feats = [], seed = 42; + function rnd() { seed = (seed * 9301 + 49297) % 233280; return seed / 233280; } + for (var i = 0; i < n; i++) { + feats.push({ type: 'Feature', properties: { cat: i % 3 }, + geometry: { type: 'Point', coordinates: [11.40 + rnd() * 0.36, 48.03 + rnd() * 0.24] } }); + } + return { type: 'FeatureCollection', features: feats }; + } + + map.on('load', function () { + map.addImage('cat0', makeIcon('#e8590c')); + map.addImage('cat1', makeIcon('#2f9e44')); + map.addImage('cat2', makeIcon('#1971c2')); + map.addSource('pois', { type: 'geojson', data: genPois(600), + cluster: true, clusterRadius: 50, clusterMaxZoom: 16 }); + map.addLayer({ id: 'clusters', type: 'circle', source: 'pois', filter: ['has', 'point_count'], + paint: { + 'circle-color': '#5b4a2f', 'circle-stroke-color': 'rgba(52,68,36,0.65)', 'circle-stroke-width': 2, + 'circle-radius': ['step', ['get', 'point_count'], 14, 10, 18, 50, 24], + } }); + map.addLayer({ id: 'poi', type: 'symbol', source: 'pois', filter: ['!', ['has', 'point_count']], + layout: { + 'icon-image': ['match', ['get', 'cat'], 0, 'cat0', 1, 'cat1', 2, 'cat2', 'cat0'], + 'icon-allow-overlap': true, 'icon-size': 0.7, + } }); + set('✅ MapLibre + 600 Marker — jetzt zoomen/schieben, fühlt sich das flüssig an?'); + }); + + map.on('error', function (e) { + set('⚠️ ' + (e && e.error ? e.error.message : 'Fehler')); + if (e && e.error) console.error(e.error); + }); + } catch (e) { + set('❌ ' + (e && e.message ? e.message : e)); + } +})(); diff --git a/backend/static/maplibre-perf-test.html b/backend/static/maplibre-perf-test.html new file mode 100644 index 0000000..a1028c7 --- /dev/null +++ b/backend/static/maplibre-perf-test.html @@ -0,0 +1,23 @@ + + + + + + Ban Yaro — MapLibre Perf-Test (600 Marker) + + + + +
+
MapLibre Perf-Test — DACH-Basemap + 600 Cluster-Marker
lädt…
+ + + + + +