feat: week view overhaul (#8)
This commit was merged in pull request #8.
This commit is contained in:
@@ -45,6 +45,10 @@ export interface ChartVariableDef {
|
||||
extrema?: boolean;
|
||||
/** Draw weather-code pictograms across the top of the chart */
|
||||
pictograms?: boolean;
|
||||
/** Draw wind-direction arrows across the top of the chart */
|
||||
windArrows?: boolean;
|
||||
/** Marker-only variable (icons / arrows): contributes no plotted series */
|
||||
marker?: boolean;
|
||||
/** Render as a puffy cloud band hanging from the top (0-100 → 0-40px) */
|
||||
cloudBand?: boolean;
|
||||
/** Transform raw values before plotting (e.g. m → km) */
|
||||
@@ -62,13 +66,21 @@ export const CHART_VARIABLES: ChartVariableDef[] = [
|
||||
type: 'line',
|
||||
kind: 'temp',
|
||||
color: '#ef6c00',
|
||||
width: 4,
|
||||
fill: true,
|
||||
fillOpacity: 0.12,
|
||||
width: 9,
|
||||
colorScale: true,
|
||||
outline: true,
|
||||
extrema: true,
|
||||
pictograms: true
|
||||
extrema: true
|
||||
},
|
||||
{
|
||||
key: 'weather_icons',
|
||||
label: 'Weather icons',
|
||||
short: 'Icons',
|
||||
field: 'weather_code',
|
||||
type: 'line',
|
||||
kind: 'temp',
|
||||
color: '#94a3b8',
|
||||
pictograms: true,
|
||||
marker: true
|
||||
},
|
||||
{
|
||||
key: 'apparent_temperature',
|
||||
@@ -189,7 +201,8 @@ export const CHART_VARIABLES: ChartVariableDef[] = [
|
||||
color: '#26a69a',
|
||||
width: 2,
|
||||
fill: true,
|
||||
fillOpacity: 0.15
|
||||
fillOpacity: 0.15,
|
||||
windArrows: true
|
||||
},
|
||||
{
|
||||
key: 'wind_gusts',
|
||||
@@ -347,7 +360,7 @@ export function isZeroBased(kind: UnitKind): boolean {
|
||||
return kind !== 'temp' && kind !== 'pressure';
|
||||
}
|
||||
|
||||
/** Sensible decimal places for tooltip / label formatting. */
|
||||
/** Decimal places for on-chart extrema labels (kept coarse, like the cards). */
|
||||
export function decimalsForKind(kind: UnitKind): number {
|
||||
switch (kind) {
|
||||
case 'precip':
|
||||
@@ -360,6 +373,20 @@ export function decimalsForKind(kind: UnitKind): number {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decimal places for the hover tooltip — finer than the cards / extrema labels
|
||||
* so the meteogram reveals more detail. Percentages stay whole numbers.
|
||||
*/
|
||||
export function tooltipDecimalsForKind(kind: UnitKind): number {
|
||||
switch (kind) {
|
||||
case 'percent':
|
||||
case 'energy':
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
export interface PanelDef {
|
||||
series: ChartSeries[];
|
||||
unit: string;
|
||||
@@ -370,6 +397,7 @@ export interface PanelDef {
|
||||
/** Whether the left axis should include zero (false for pressure) */
|
||||
zeroBaseLeft: boolean;
|
||||
hasPictograms: boolean;
|
||||
hasWindArrows: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -382,10 +410,13 @@ export function buildPanelDef(
|
||||
hourly: WeekHourlyData,
|
||||
units: WeatherUnits
|
||||
): PanelDef {
|
||||
const defs = variableKeys
|
||||
const allDefs = variableKeys
|
||||
.map((k) => VARIABLE_BY_KEY.get(k))
|
||||
.filter((d): d is ChartVariableDef => d != null);
|
||||
|
||||
// Marker-only variables (weather icons) render no series, just a top row.
|
||||
const defs = allDefs.filter((d) => !d.marker);
|
||||
|
||||
// Cloud-band variables float above the plot and don't claim an axis.
|
||||
const axisDefs = defs.filter((d) => !d.cloudBand);
|
||||
const kinds: UnitKind[] = [];
|
||||
@@ -400,6 +431,7 @@ export function buildPanelDef(
|
||||
: raw;
|
||||
const kindUnit = unitForKind(d.kind, units);
|
||||
const dec = decimalsForKind(d.kind);
|
||||
const tipDec = tooltipDecimalsForKind(d.kind);
|
||||
const axis: 'left' | 'right' = d.cloudBand || d.kind === leftKind ? 'left' : 'right';
|
||||
|
||||
return {
|
||||
@@ -425,9 +457,9 @@ export function buildPanelDef(
|
||||
? (v: number, i: number) => {
|
||||
const dir = hourly.winddirection_10m?.[i];
|
||||
const dl = dir != null && !isNaN(dir) ? ` (${getWindDirectionLabel(dir)})` : '';
|
||||
return `${v.toFixed(dec)} ${kindUnit}${dl}`;
|
||||
return `${v.toFixed(tipDec)} ${kindUnit}${dl}`;
|
||||
}
|
||||
: (v: number) => `${v.toFixed(dec)}${kindUnit ? ' ' + kindUnit : ''}`
|
||||
: (v: number) => `${v.toFixed(tipDec)}${kindUnit ? ' ' + kindUnit : ''}`
|
||||
} satisfies ChartSeries;
|
||||
});
|
||||
|
||||
@@ -441,6 +473,7 @@ export function buildPanelDef(
|
||||
zeroBaseLeft: leftKind !== 'pressure',
|
||||
yMinRight: rightKind && rightZero ? 0 : undefined,
|
||||
yMaxRight: rightKind === 'percent' ? 100 : undefined,
|
||||
hasPictograms: defs.some((d) => d.pictograms)
|
||||
hasPictograms: allDefs.some((d) => d.pictograms),
|
||||
hasWindArrows: allDefs.some((d) => d.windArrows)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user