Add data_visualization/js/chartRenderer.js
This commit is contained in:
parent
3dfa8d1208
commit
a36a0210db
1 changed files with 137 additions and 0 deletions
137
data_visualization/js/chartRenderer.js
Normal file
137
data_visualization/js/chartRenderer.js
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
(() => {
|
||||||
|
/**
|
||||||
|
* chartRenderer.js
|
||||||
|
* Visualization layer rendering measurement data charts.
|
||||||
|
* Uses Chart.js (assumed pre-loaded in the environment)
|
||||||
|
* Handles rendering and updating of multiple measurement charts.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let charts = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts measurement data into Chart.js datasets
|
||||||
|
* @param {Array<Object>} data - filtered measurement records
|
||||||
|
* @returns {Object} datasets and labels for Chart.js
|
||||||
|
*/
|
||||||
|
const prepareDatasets = (data) => {
|
||||||
|
if (!Array.isArray(data)) return { labels: [], datasets: [] };
|
||||||
|
const labels = data.map(d => new Date(d.timestamp).toLocaleTimeString());
|
||||||
|
|
||||||
|
const temperatureData = data.map(d => d.temperature);
|
||||||
|
const humidityData = data.map(d => d.humidity);
|
||||||
|
const brightnessData = data.map(d => d.brightness);
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Temperatur (°C)',
|
||||||
|
data: temperatureData,
|
||||||
|
borderColor: 'rgba(255, 99, 132, 1)',
|
||||||
|
backgroundColor: 'rgba(255, 99, 132, 0.2)',
|
||||||
|
tension: 0.3,
|
||||||
|
yAxisID: 'y',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Luftfeuchte (%)',
|
||||||
|
data: humidityData,
|
||||||
|
borderColor: 'rgba(54, 162, 235, 1)',
|
||||||
|
backgroundColor: 'rgba(54, 162, 235, 0.2)',
|
||||||
|
tension: 0.3,
|
||||||
|
yAxisID: 'y1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Signalintensität',
|
||||||
|
data: brightnessData,
|
||||||
|
borderColor: 'rgba(75, 192, 192, 1)',
|
||||||
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||||
|
tension: 0.3,
|
||||||
|
yAxisID: 'y',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* renderCharts
|
||||||
|
* Visualizes data in line charts and appends them into the .chart-panel.
|
||||||
|
* @param {Array<Object>} data - filtered measurement data
|
||||||
|
*/
|
||||||
|
const renderCharts = (data) => {
|
||||||
|
const chartPanel = document.querySelector('.chart-panel');
|
||||||
|
if (!chartPanel) return;
|
||||||
|
|
||||||
|
chartPanel.innerHTML = '';
|
||||||
|
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
canvas.setAttribute('aria-label', 'Messdaten Diagramm');
|
||||||
|
canvas.setAttribute('role', 'img');
|
||||||
|
chartPanel.appendChild(canvas);
|
||||||
|
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const { labels, datasets } = prepareDatasets(data);
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
type: 'line',
|
||||||
|
data: { labels, datasets },
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
interaction: { mode: 'index', intersect: false },
|
||||||
|
stacked: false,
|
||||||
|
plugins: {
|
||||||
|
tooltip: {
|
||||||
|
enabled: true,
|
||||||
|
callbacks: {
|
||||||
|
title: (items) => items[0]?.label || '',
|
||||||
|
label: (item) => `${item.dataset.label}: ${item.formattedValue}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: { labels: { color: '#eee' } },
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
type: 'linear',
|
||||||
|
display: true,
|
||||||
|
position: 'left',
|
||||||
|
title: { display: true, text: 'Temperatur / Intensität' },
|
||||||
|
ticks: { color: '#ccc' }
|
||||||
|
},
|
||||||
|
y1: {
|
||||||
|
type: 'linear',
|
||||||
|
display: true,
|
||||||
|
position: 'right',
|
||||||
|
grid: { drawOnChartArea: false },
|
||||||
|
title: { display: true, text: 'Luftfeuchte' },
|
||||||
|
ticks: { color: '#ccc' }
|
||||||
|
},
|
||||||
|
x: {
|
||||||
|
ticks: { color: '#ccc' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
charts.main = new Chart(ctx, config);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* updateChart
|
||||||
|
* Updates existing chart data and re-renders with new dataset.
|
||||||
|
* @param {Array<Object>} newData - new or filtered measurement data
|
||||||
|
*/
|
||||||
|
const updateChart = (newData) => {
|
||||||
|
if (!charts.main) {
|
||||||
|
renderCharts(newData);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { labels, datasets } = prepareDatasets(newData);
|
||||||
|
|
||||||
|
charts.main.data.labels = labels;
|
||||||
|
charts.main.data.datasets = datasets;
|
||||||
|
charts.main.update('active');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expose functions globally
|
||||||
|
window.chartRenderer = { renderCharts, updateChart };
|
||||||
|
})();
|
||||||
Loading…
Reference in a new issue