82 lines
No EOL
2.8 KiB
JavaScript
82 lines
No EOL
2.8 KiB
JavaScript
/* 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 = `
|
|
<h2>Signalstatistik</h2>
|
|
<ul>
|
|
<li><strong>Messpunkte:</strong> ${values.length}</li>
|
|
<li><strong>Minimum RSSI:</strong> ${min.toFixed(1)} dBm</li>
|
|
<li><strong>Maximum RSSI:</strong> ${max.toFixed(1)} dBm</li>
|
|
<li><strong>Median RSSI:</strong> ${median.toFixed(1)} dBm</li>
|
|
</ul>
|
|
`;
|
|
}
|
|
|
|
/**
|
|
* 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.
|