123 lines
3.7 KiB
JavaScript
123 lines
3.7 KiB
JavaScript
/**
|
||
* js/charts.js
|
||
* Visualisierung der Laufdaten in Matrix- und Zeitdiagrammen.
|
||
* Enthält Funktionen zur DOM-Aktualisierung von #delta-matrix und #timeline-chart.
|
||
* @module charts
|
||
*/
|
||
|
||
/**
|
||
* Rendert eine 2×2-Matrix aus den gegebenen aggregierten Daten.
|
||
* Die Matrix zeigt pinned/unpinned (x) vs. Δt≥0/<0 (y).
|
||
* @param {Object} data - Aggregierte Daten in der Form:
|
||
* {
|
||
* pinned_pos: number,
|
||
* pinned_neg: number,
|
||
* unpinned_pos: number,
|
||
* unpinned_neg: number
|
||
* }
|
||
*/
|
||
export function renderDeltaMatrix(data) {
|
||
const container = document.getElementById('delta-matrix');
|
||
if (!container) return;
|
||
|
||
container.innerHTML = '';
|
||
|
||
const matrixData = [
|
||
{ label: 'Pinned Δt≥0', value: data?.pinned_pos ?? 0 },
|
||
{ label: 'Pinned Δt<0', value: data?.pinned_neg ?? 0 },
|
||
{ label: 'Unpinned Δt≥0', value: data?.unpinned_pos ?? 0 },
|
||
{ label: 'Unpinned Δt<0', value: data?.unpinned_neg ?? 0 }
|
||
];
|
||
|
||
const matrixGrid = document.createElement('div');
|
||
matrixGrid.className = 'delta-matrix__grid';
|
||
matrixGrid.style.display = 'grid';
|
||
matrixGrid.style.gridTemplateColumns = 'repeat(2, 1fr)';
|
||
matrixGrid.style.gap = '1rem';
|
||
|
||
matrixData.forEach(cell => {
|
||
const cellDiv = document.createElement('div');
|
||
cellDiv.className = 'delta-matrix__cell';
|
||
cellDiv.setAttribute('role', 'region');
|
||
cellDiv.setAttribute('aria-label', cell.label);
|
||
|
||
const label = document.createElement('div');
|
||
label.className = 'delta-matrix__label';
|
||
label.textContent = cell.label;
|
||
|
||
const value = document.createElement('div');
|
||
value.className = 'delta-matrix__value';
|
||
value.textContent = cell.value.toFixed(2);
|
||
|
||
cellDiv.appendChild(label);
|
||
cellDiv.appendChild(value);
|
||
matrixGrid.appendChild(cellDiv);
|
||
});
|
||
|
||
container.appendChild(matrixGrid);
|
||
}
|
||
|
||
/**
|
||
* Rendert den zeitlichen Verlauf der Δt-Werte als Liniendiagramm.
|
||
* Nutzt Canvas API (ohne externes Chart-Framework).
|
||
* @param {Array<{timestamp: string|number, delta_t: number}>} timeData - Zeitreihen-Daten.
|
||
*/
|
||
export function renderTimelineChart(timeData) {
|
||
const container = document.getElementById('timeline-chart');
|
||
if (!container) return;
|
||
|
||
container.innerHTML = '';
|
||
|
||
const canvas = document.createElement('canvas');
|
||
canvas.width = container.clientWidth || 600;
|
||
canvas.height = 300;
|
||
container.appendChild(canvas);
|
||
|
||
const ctx = canvas.getContext('2d');
|
||
if (!ctx || !Array.isArray(timeData) || timeData.length === 0) {
|
||
ctx.fillStyle = '#666';
|
||
ctx.fillText('Keine Daten verfügbar', 20, 40);
|
||
return;
|
||
}
|
||
|
||
const maxVal = Math.max(...timeData.map(d => d.delta_t));
|
||
const minVal = Math.min(...timeData.map(d => d.delta_t));
|
||
|
||
const normalize = v => (v - minVal) / (maxVal - minVal || 1);
|
||
|
||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||
ctx.beginPath();
|
||
ctx.lineWidth = 2;
|
||
ctx.strokeStyle = '#0077cc';
|
||
|
||
timeData.forEach((point, i) => {
|
||
const x = (i / (timeData.length - 1)) * (canvas.width - 40) + 20;
|
||
const y = canvas.height - (normalize(point.delta_t) * (canvas.height - 40) + 20);
|
||
if (i === 0) ctx.moveTo(x, y);
|
||
else ctx.lineTo(x, y);
|
||
});
|
||
|
||
ctx.stroke();
|
||
|
||
// Achsen zeichnen
|
||
ctx.strokeStyle = '#333';
|
||
ctx.lineWidth = 1;
|
||
ctx.beginPath();
|
||
ctx.moveTo(20, 10);
|
||
ctx.lineTo(20, canvas.height - 20);
|
||
ctx.lineTo(canvas.width - 20, canvas.height - 20);
|
||
ctx.stroke();
|
||
|
||
// Beschriftungen
|
||
ctx.fillStyle = '#222';
|
||
ctx.font = '12px sans-serif';
|
||
ctx.fillText('Zeit', canvas.width / 2 - 20, canvas.height - 5);
|
||
ctx.save();
|
||
ctx.rotate(-Math.PI / 2);
|
||
ctx.fillText('Δt', -canvas.height / 2 - 10, 10);
|
||
ctx.restore();
|
||
|
||
// Accessibility-Hinweis
|
||
canvas.setAttribute('role', 'img');
|
||
canvas.setAttribute('aria-label', 'Liniendiagramm der Δt-Zeitverteilung');
|
||
}
|