temperature chart and table alignments
This commit is contained in:
@@ -165,6 +165,21 @@
|
||||
unit: string;
|
||||
showCredit: boolean;
|
||||
series: ChartSeries[];
|
||||
zeroBaseLeft?: boolean;
|
||||
yMin?: number;
|
||||
yMax?: number;
|
||||
}
|
||||
|
||||
// Sensible axis behaviour per variable so the y-scale stays readable (e.g.
|
||||
// pressure never anchored to zero; percentages pinned to 0-100).
|
||||
function axisForVar(v: string): { zeroBaseLeft: boolean; yMin?: number; yMax?: number } {
|
||||
if (['pressure_msl', 'surface_pressure', 'temperature_2m', 'dew_point_2m'].includes(v)) {
|
||||
return { zeroBaseLeft: false };
|
||||
}
|
||||
if (['relative_humidity_2m', 'cloud_cover', 'precipitation_probability'].includes(v)) {
|
||||
return { zeroBaseLeft: true, yMin: 0, yMax: 100 };
|
||||
}
|
||||
return { zeroBaseLeft: true };
|
||||
}
|
||||
|
||||
const BAND_COLOR = 'rgba(115, 192, 222, 0.9)';
|
||||
@@ -202,33 +217,40 @@
|
||||
const isColumn = isColumnUnit(unit);
|
||||
const memberCount = varData.members.length;
|
||||
|
||||
// Trim to the valid horizon so the axis scale ignores the trailing
|
||||
// zeros the service pads past the model's range.
|
||||
const vMax = varData.max.slice(0, validLength);
|
||||
const vMin = varData.min.slice(0, validLength);
|
||||
const vAvg = varData.average.slice(0, validLength);
|
||||
|
||||
// Min/max spread band + mean, instead of every individual member
|
||||
const series: ChartSeries[] = [
|
||||
{
|
||||
name: 'Max',
|
||||
type: 'line',
|
||||
color: BAND_COLOR,
|
||||
data: varData.max,
|
||||
data: vMax,
|
||||
width: 1,
|
||||
fill: true,
|
||||
fillOpacity: 0.25,
|
||||
bandTo: varData.min,
|
||||
bandTo: vMin,
|
||||
format: (v) => `${v.toFixed(1)} ${unit}`
|
||||
},
|
||||
{
|
||||
name: 'Mean',
|
||||
type: isColumn ? 'bar' : 'line',
|
||||
color: CHART_COLORS.average,
|
||||
data: varData.average,
|
||||
width: 3,
|
||||
data: vAvg,
|
||||
width: 3.5,
|
||||
dashed: !isColumn,
|
||||
outline: !isColumn,
|
||||
format: (v) => `${v.toFixed(1)} ${unit}`
|
||||
},
|
||||
{
|
||||
name: 'Min',
|
||||
type: 'line',
|
||||
color: BAND_COLOR,
|
||||
data: varData.min,
|
||||
data: vMin,
|
||||
width: 1,
|
||||
format: (v) => `${v.toFixed(1)} ${unit}`
|
||||
}
|
||||
@@ -237,6 +259,7 @@
|
||||
const isFirst = vi === 0;
|
||||
const isLast = vi === variables.length - 1;
|
||||
|
||||
const axis = axisForVar(variable);
|
||||
defs.push({
|
||||
// each chart is labelled so the variable is obvious at a glance
|
||||
title: `${varLabel(variable)}${isColumn ? '' : ' spread'}`,
|
||||
@@ -245,7 +268,10 @@
|
||||
: `min · mean · max (${unit})`,
|
||||
unit,
|
||||
showCredit: isLast,
|
||||
series
|
||||
series,
|
||||
zeroBaseLeft: axis.zeroBaseLeft,
|
||||
yMin: axis.yMin,
|
||||
yMax: axis.yMax
|
||||
});
|
||||
}
|
||||
|
||||
@@ -255,7 +281,7 @@
|
||||
|
||||
<!-- ─── Page hero: location + ensemble model selection ─────────────────────── -->
|
||||
|
||||
<div class="mb-5 flex flex-wrap items-center justify-between gap-x-6 gap-y-3">
|
||||
<div class="relative mb-3 flex flex-wrap items-center justify-between gap-x-6 gap-y-3 md:mb-5">
|
||||
<div class="flex min-w-0 items-center gap-3">
|
||||
<img
|
||||
class="h-10 w-10 shrink-0 rounded-full shadow-sm ring-2 ring-border"
|
||||
@@ -275,7 +301,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex w-full items-center gap-3 sm:w-auto">
|
||||
<div class="lg:absolute lg:right-0 lg:top-0 flex w-full items-center gap-3 sm:w-auto">
|
||||
<ModelSelector
|
||||
selectedModel={params.models?.[0] ?? 'ncep_gefs_seamless'}
|
||||
groups={ensembleModelGroups}
|
||||
@@ -322,7 +348,7 @@
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<ChartContainer {loading} chartCount={params.hourly?.length || 1} chartHeight={300}>
|
||||
<ChartContainer {loading} chartCount={params.hourly?.length || 1} chartHeight={300} bleed={false}>
|
||||
{#if fetchedData}
|
||||
{#each chartDefs as def, i (i)}
|
||||
<CanvasChart
|
||||
@@ -335,6 +361,9 @@
|
||||
title={def.title}
|
||||
subtitle={def.subtitle}
|
||||
showCredit={def.showCredit}
|
||||
zeroBaseLeft={def.zeroBaseLeft ?? true}
|
||||
yMin={def.yMin}
|
||||
yMax={def.yMax}
|
||||
{showLegend}
|
||||
height={300}
|
||||
group={CHART_GROUP}
|
||||
|
||||
Reference in New Issue
Block a user