feat: roseta de los vientos con Chart.js polarArea
This commit is contained in:
parent
9ecf4114ba
commit
b457a8d614
|
|
@ -117,6 +117,19 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ROSETA DE VIENTOS -->
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card project-card h-100">
|
||||
<div class="card-body d-flex flex-column">
|
||||
<h5 class="card-title fw-bold">Rosa de los vientos</h5>
|
||||
<p class="text-muted small mb-2">Frecuencia por dirección — mes seleccionado</p>
|
||||
<div class="flex-grow-1 d-flex align-items-center justify-content-center">
|
||||
<canvas id="wind-rose" style="max-width:280px; max-height:280px;"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
|
|
@ -127,6 +140,7 @@
|
|||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/estadisticas.js?v=2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.2/dist/chart.umd.min.js"></script>
|
||||
<script src="js/estadisticas.js?v=3"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ async function loadStats(options = {}) {
|
|||
|
||||
renderMonthStats(data);
|
||||
renderTrend(data);
|
||||
renderWindRose(data);
|
||||
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
|
@ -253,6 +254,92 @@ function renderTrend(data) {
|
|||
container.innerHTML = html;
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Rosa de los vientos
|
||||
// ====================
|
||||
let windRoseChart = null;
|
||||
|
||||
function renderWindRose(data) {
|
||||
const sectors = [
|
||||
{ label: "N", min: 337.5, max: 360 },
|
||||
{ label: "N", min: 0, max: 22.5 },
|
||||
{ label: "NE", min: 22.5, max: 67.5 },
|
||||
{ label: "E", min: 67.5, max: 112.5 },
|
||||
{ label: "SE", min: 112.5, max: 157.5 },
|
||||
{ label: "S", min: 157.5, max: 202.5 },
|
||||
{ label: "SO", min: 202.5, max: 247.5 },
|
||||
{ label: "O", min: 247.5, max: 292.5 },
|
||||
{ label: "NO", min: 292.5, max: 337.5 }
|
||||
];
|
||||
|
||||
// Filtrar por mes seleccionado y agrupar por día para no contar duplicados horarios
|
||||
const byDay = {};
|
||||
data.forEach(d => {
|
||||
const date = new Date(d.dia);
|
||||
if (date.getMonth() === selectedMonth) {
|
||||
if (!byDay[d.dia]) byDay[d.dia] = [];
|
||||
byDay[d.dia].push(parseFloat(d.viento_direccion));
|
||||
}
|
||||
});
|
||||
|
||||
// Por cada día usar la dirección media del día
|
||||
const direcciones = Object.values(byDay).map(dirs => {
|
||||
return dirs.reduce((a, b) => a + b, 0) / dirs.length;
|
||||
});
|
||||
|
||||
// Contar frecuencia por sector (N agrupa los dos rangos)
|
||||
const counts = { N: 0, NE: 0, E: 0, SE: 0, S: 0, SO: 0, O: 0, NO: 0 };
|
||||
direcciones.forEach(deg => {
|
||||
for (const s of sectors) {
|
||||
if (deg >= s.min && deg < s.max) {
|
||||
counts[s.label]++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const labels = ["N", "NE", "E", "SE", "S", "SO", "O", "NO"];
|
||||
const values = labels.map(l => counts[l]);
|
||||
const accent = "rgba(164, 215, 244, 0.75)";
|
||||
const border = "rgba(164, 215, 244, 1)";
|
||||
|
||||
const canvas = $("wind-rose");
|
||||
if (!canvas) return;
|
||||
|
||||
if (windRoseChart) windRoseChart.destroy();
|
||||
|
||||
windRoseChart = new Chart(canvas, {
|
||||
type: "polarArea",
|
||||
data: {
|
||||
labels,
|
||||
datasets: [{
|
||||
data: values,
|
||||
backgroundColor: labels.map(() => accent),
|
||||
borderColor: labels.map(() => border),
|
||||
borderWidth: 1
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
responsive: true,
|
||||
plugins: {
|
||||
legend: { display: false },
|
||||
tooltip: {
|
||||
callbacks: {
|
||||
label: ctx => ` ${ctx.label}: ${ctx.raw} días`
|
||||
}
|
||||
}
|
||||
},
|
||||
scales: {
|
||||
r: {
|
||||
ticks: { color: "#888", font: { size: 10 }, backdropColor: "transparent" },
|
||||
grid: { color: "rgba(255,255,255,0.1)" },
|
||||
pointLabels: { color: "#a4d7f4", font: { size: 12 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ====================
|
||||
// Cargar mes actual según selectedMonth
|
||||
// ====================
|
||||
|
|
|
|||
Loading…
Reference in New Issue