fix: replace misleading chart labels with OM model vs METAR scatter overlay

This commit is contained in:
2569718930@qq.com
2026-03-04 02:16:14 +08:00
parent 0ce9ec25c3
commit c8e411d3af
+43 -14
View File
@@ -424,20 +424,35 @@ function renderChart(data) {
: null; : null;
const curIdx = curHour ? times.indexOf(curHour) : -1; const curIdx = curHour ? times.indexOf(curHour) : -1;
// Forecast vs actual split // Open-Meteo model: past = solid, future = dashed
const actualTemps = temps.map((t, i) => const pastTemps = temps.map((t, i) =>
curIdx >= 0 && i <= curIdx ? t : null, curIdx >= 0 && i <= curIdx ? t : null,
); );
const forecastTemps = temps.map((t, i) => const futureTemps = temps.map((t, i) =>
curIdx < 0 || i >= curIdx ? t : null, curIdx < 0 || i >= curIdx ? t : null,
); );
// METAR observation scatter points
const metarPoints = new Array(times.length).fill(null);
const metarRecent = data.trend?.recent || [];
if (metarRecent.length > 0) {
metarRecent.forEach((r) => {
// Match METAR time (e.g. "15:00") to chart time labels
const idx = times.indexOf(r.time);
if (idx >= 0) {
metarPoints[idx] = r.temp;
}
});
}
const ctx = document.getElementById("tempChart").getContext("2d"); const ctx = document.getElementById("tempChart").getContext("2d");
if (tempChart) tempChart.destroy(); if (tempChart) tempChart.destroy();
const validTemps = temps.filter((t) => t != null); const validTemps = temps.filter((t) => t != null);
const minTemp = Math.floor(Math.min(...validTemps)) - 1; const validMetar = metarPoints.filter((t) => t != null);
const maxTemp = Math.ceil(Math.max(...validTemps)) + 1; const allVals = [...validTemps, ...validMetar];
const minTemp = Math.floor(Math.min(...allVals)) - 1;
const maxTemp = Math.ceil(Math.max(...allVals)) + 1;
tempChart = new Chart(ctx, { tempChart = new Chart(ctx, {
type: "line", type: "line",
@@ -445,21 +460,21 @@ function renderChart(data) {
labels: times, labels: times,
datasets: [ datasets: [
{ {
label: "实测", label: "OM模型",
data: actualTemps, data: pastTemps,
borderColor: "#22d3ee", borderColor: "rgba(99, 102, 241, 0.5)",
backgroundColor: "rgba(34, 211, 238, 0.1)", backgroundColor: "rgba(99, 102, 241, 0.05)",
borderWidth: 2.5, borderWidth: 1.5,
pointRadius: 0, pointRadius: 0,
pointHoverRadius: 4, pointHoverRadius: 3,
fill: true, fill: true,
tension: 0.3, tension: 0.3,
spanGaps: false, spanGaps: false,
}, },
{ {
label: "预报", label: "OM预报",
data: forecastTemps, data: futureTemps,
borderColor: "rgba(99, 102, 241, 0.6)", borderColor: "rgba(99, 102, 241, 0.4)",
borderWidth: 1.5, borderWidth: 1.5,
borderDash: [5, 3], borderDash: [5, 3],
pointRadius: 0, pointRadius: 0,
@@ -467,6 +482,19 @@ function renderChart(data) {
tension: 0.3, tension: 0.3,
spanGaps: false, spanGaps: false,
}, },
{
label: "METAR实测",
data: metarPoints,
borderColor: "#22d3ee",
backgroundColor: "#22d3ee",
borderWidth: 0,
pointRadius: 5,
pointHoverRadius: 7,
pointStyle: "circle",
fill: false,
showLine: false,
order: 0, // Draw on top
},
], ],
}, },
options: { options: {
@@ -481,6 +509,7 @@ function renderChart(data) {
borderWidth: 1, borderWidth: 1,
titleFont: { family: "Inter", size: 12 }, titleFont: { family: "Inter", size: 12 },
bodyFont: { family: "Inter", size: 12 }, bodyFont: { family: "Inter", size: 12 },
filter: (item) => item.parsed.y != null,
callbacks: { callbacks: {
label: (ctx) => label: (ctx) =>
`${ctx.dataset.label}: ${ctx.parsed.y?.toFixed(1)}${data.temp_symbol}`, `${ctx.dataset.label}: ${ctx.parsed.y?.toFixed(1)}${data.temp_symbol}`,