diff --git a/data_visualization/js/visualization.js b/data_visualization/js/visualization.js new file mode 100644 index 0000000..9bdb295 --- /dev/null +++ b/data_visualization/js/visualization.js @@ -0,0 +1,82 @@ +/* eslint-env browser */ + +/** + * Modul: visualization.js + * Rolle: render_logic + * Beschreibung: Rendering der Heatmap und Statistikaktualisierung basierend auf WLAN-Messdaten. + */ + +/** + * Aktualisiert die Statistik-Seitenleiste basierend auf den aktuellen Heatmap-Daten. + * @param {Array<{location: {lat: number, lng: number}, intensity: number, rssi?: number}>} heatmap_data - Messdaten + */ +export function updateStatsPanel(heatmap_data = []) { + const statsPanel = document.getElementById('stats-panel'); + if (!statsPanel || heatmap_data.length === 0) return; + + // Extrahiere Signalstärken (RSSI oder intensity) + const values = heatmap_data.map(p => p.rssi ?? p.intensity).filter(v => typeof v === 'number'); + if (values.length === 0) return; + + const sorted = [...values].sort((a, b) => a - b); + const min = sorted[0]; + const max = sorted[sorted.length - 1]; + const median = sorted[Math.floor(sorted.length / 2)]; + + statsPanel.innerHTML = ` +

Signalstatistik

+ + `; +} + +/** + * Rendert die Heatmap über der Karte. + * @param {Array<{location: {lat: number, lng: number}, intensity: number}>} heatmap_data - WLAN-Daten + */ +export function render_heatmap(heatmap_data = []) { + // Defensive: Canvas- oder Map-Element prüfen + const canvas = document.getElementById('heatmap-canvas'); + if (!canvas) return; + const ctx = canvas.getContext('2d'); + const width = canvas.width; + const height = canvas.height; + ctx.clearRect(0, 0, width, height); + + // Einfache farbliche Darstellung basierend auf Intensität + heatmap_data.forEach(point => { + const { lat, lng } = point.location || {}; + if (typeof lat !== 'number' || typeof lng !== 'number') return; + + // Beispielkonversion: fiktives Mapping lat/lng -> Canvas-Koordinaten + const x = ((lng + 180) / 360) * width; + const y = ((90 - lat) / 180) * height; + + const intensity = Math.max(0, Math.min(1, point.intensity ?? 0)); + const radius = 20 + intensity * 30; + + const gradient = ctx.createRadialGradient(x, y, 0, x, y, radius); + gradient.addColorStop(0, `rgba(255, 0, 0, ${0.4 * intensity})`); + gradient.addColorStop(1, 'rgba(255, 0, 0, 0)'); + + ctx.beginPath(); + ctx.fillStyle = gradient; + ctx.arc(x, y, radius, 0, 2 * Math.PI); + ctx.fill(); + }); + + // Statistiken nach Rendering aktualisieren + updateStatsPanel(heatmap_data); + + // Accessibility-Update, z. B. für Screenreader + const liveRegion = document.getElementById('heatmap-live'); + if (liveRegion) { + liveRegion.textContent = `Heatmap aktualisiert: ${heatmap_data.length} Punkte.`; + } +} + +// Hinweis: Dieses Modul wird von app.refreshData aufgerufen. \ No newline at end of file