Karte: MarkerCluster mit Popups, Hero-CTAs scrollen zu Demos

Lagebild-Karte auf geclusterte Marker umgebaut (primary/secondary als Pulse, rest als CircleMarker). Popups zeigen jetzt Top-Artikel mit Links. Vorschau Hero-Buttons scrollen zum Demo-Karussell statt direkt zu den Lagen.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dieser Commit ist enthalten in:
Claude Code
2026-04-11 18:18:31 +02:00
Ursprung 3cd5623fa6
Commit 0a6ec07374
6 geänderte Dateien mit 130 neuen und 25 gelöschten Zeilen

Datei anzeigen

@@ -655,7 +655,7 @@ var Lagebild = {
renderArticlesTab: function() {},
/* ===== TAB: KARTE (Pulse Markers) ===== */
/* ===== TAB: KARTE (Clustered Pulse Markers) ===== */
renderMap: function() {
if (this.map) { this.map.remove(); this.map = null; }
this.map = L.map('map-container', {
@@ -664,7 +664,6 @@ var Lagebild = {
maxBoundsViscosity: 1.0
}).setView([33.0, 48.0], 5);
// Deutsche OSM-Kacheln
L.tileLayer('https://tile.openstreetmap.de/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>',
maxZoom: 19,
@@ -685,7 +684,6 @@ var Lagebild = {
});
}
// Kategorie-Farben
var categoryColors = {
primary: '#ef4444',
secondary: '#f59e0b',
@@ -698,7 +696,6 @@ var Lagebild = {
tertiary: 'Beteiligte',
mentioned: 'Erwaehnt'
};
// Dynamische Labels aus API verwenden (falls vorhanden)
var categoryLabels = {};
if (this.data && this.data.category_labels) {
var apiLabels = this.data.category_labels;
@@ -710,7 +707,6 @@ var Lagebild = {
categoryLabels = defaultCategoryLabels;
}
// Locations aus API-Daten laden
var locs = (this.data && this.data.locations) ? this.data.locations : [];
if (locs.length === 0) {
@@ -720,22 +716,60 @@ var Lagebild = {
document.getElementById('map-container').appendChild(emptyDiv);
}
var clusterGroup = L.markerClusterGroup({
maxClusterRadius: 50,
spiderfyOnMaxZoom: true,
showCoverageOnHover: false,
zoomToBoundsOnClick: true,
disableClusteringAtZoom: 10
});
var usedCategories = {};
var bounds = [];
for (var i = 0; i < locs.length; i++) {
var l = locs[i];
if (!l.lat || !l.lon) continue;
var cat = l.category || 'mentioned';
var color = categoryColors[cat] || '#7b7b7b';
usedCategories[cat] = true;
// Popup mit Artikel-Links
var popupText = '<strong style="color:#E8ECF4;">' + (l.name || '') + '</strong>';
if (l.country_code) popupText += ' <span style="color:#8896AB;font-size:0.8rem;">(' + l.country_code + ')</span>';
popupText += '<br><span style="font-size:0.85rem;color:#8896AB;">' + (l.article_count || 0) + ' Artikel</span>';
L.marker([l.lat, l.lon], { icon: pulseIcon(color) })
.addTo(this.map)
.bindPopup(popupText);
if (l.top_articles && l.top_articles.length > 0) {
popupText += '<div style="margin-top:6px;border-top:1px solid #1E2D45;padding-top:6px;">';
for (var j = 0; j < l.top_articles.length; j++) {
var a = l.top_articles[j];
var hl = (a.headline || '').replace(/\*\*/g, '');
if (hl.length > 60) hl = hl.substring(0, 60) + '\u2026';
if (a.url) {
popupText += '<a href="' + a.url + '" target="_blank" rel="noopener" style="color:#C8A851;font-size:0.8rem;display:block;margin-top:3px;text-decoration:none;">' + hl + '</a>';
} else {
popupText += '<span style="color:#8896AB;font-size:0.8rem;display:block;margin-top:3px;">' + hl + '</span>';
}
popupText += '<span style="color:#556B7A;font-size:0.7rem;">' + (a.source || '') + '</span>';
}
popupText += '</div>';
}
var marker;
if (cat === 'primary' || cat === 'secondary') {
marker = L.marker([l.lat, l.lon], { icon: pulseIcon(color) });
} else {
marker = L.circleMarker([l.lat, l.lon], {
radius: 5, fillColor: color, fillOpacity: 0.7,
color: color, weight: 1, opacity: 0.9
});
}
marker.bindPopup(popupText, { maxWidth: 300 });
clusterGroup.addLayer(marker);
bounds.push([l.lat, l.lon]);
}
// Dark legend (dynamisch)
this.map.addLayer(clusterGroup);
// Dark legend
var legend = L.control({ position: 'bottomright' });
legend.onAdd = function() {
var div = L.DomUtil.create('div', 'map-legend');
@@ -751,6 +785,10 @@ var Lagebild = {
};
legend.addTo(this.map);
if (bounds.length > 0) {
this.map.fitBounds(bounds, { padding: [30, 30], maxZoom: 7 });
}
// Dark popup styling
if (!document.getElementById('leaflet-dark-style')) {
var style = document.createElement('style');