1.9.1.2
Uniform temperature shades
This commit is contained in:
+50
-23
@@ -570,20 +570,47 @@ ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeC
|
|||||||
const fmt = (v, dp = 1) => v == null ? '—' : (showDecimals ? v.toFixed(dp) : String(Math.round(v)));
|
const fmt = (v, dp = 1) => v == null ? '—' : (showDecimals ? v.toFixed(dp) : String(Math.round(v)));
|
||||||
const u = (unit) => showUnits ? unit : '';
|
const u = (unit) => showUnits ? unit : '';
|
||||||
// Returns a background tint based on temperature value - all share the same
|
// Returns a background tint based on temperature value - all share the same
|
||||||
// Thermal Stress Bands - solid colours matching the legend exactly.
|
// Continuous temperature colour scale — used for all temp columns
|
||||||
// All band-coloured cells use the full bg/fg from UTCI_BANDS.
|
// (air, dew, indoor, vehicle, concrete, soil, UTCI, SunSoak…).
|
||||||
const tempBg = (t) => {
|
// Fully opaque, richly saturated stops so every degree is distinct.
|
||||||
|
const airTempBg = (t) => {
|
||||||
if (t == null) return 'transparent';
|
if (t == null) return 'transparent';
|
||||||
const band = utciCategory(t);
|
// [temp °C, [r,g,b]]
|
||||||
return band ? bandGradient(band.bg, band.darkenAmt) : 'transparent';
|
const stops = [
|
||||||
|
[-10, [ 90, 155, 220]],
|
||||||
|
[ 0, [140, 195, 235]],
|
||||||
|
[ 10, [155, 215, 195]],
|
||||||
|
[ 16, [140, 210, 140]],
|
||||||
|
[ 20, [195, 225, 110]],
|
||||||
|
[ 24, [240, 225, 80]],
|
||||||
|
[ 28, [250, 175, 65]],
|
||||||
|
[ 32, [240, 120, 55]],
|
||||||
|
[ 36, [220, 70, 50]],
|
||||||
|
[ 40, [185, 30, 30]],
|
||||||
|
[ 50, [130, 0, 20]],
|
||||||
|
];
|
||||||
|
const clamp = (v, lo, hi) => Math.max(lo, Math.min(hi, v));
|
||||||
|
let i = stops.findIndex(s => t < s[0]);
|
||||||
|
if (i === -1) i = stops.length;
|
||||||
|
const baseRgb = i === 0 ? stops[0][1]
|
||||||
|
: i >= stops.length ? stops[stops.length-1][1]
|
||||||
|
: (() => {
|
||||||
|
const [t0, c0] = stops[i-1];
|
||||||
|
const [t1, c1] = stops[i];
|
||||||
|
const x = clamp((t - t0) / (t1 - t0), 0, 1);
|
||||||
|
const lerp = (a, b) => Math.round(a + (b - a) * x);
|
||||||
|
return [lerp(c0[0],c1[0]), lerp(c0[1],c1[1]), lerp(c0[2],c1[2])];
|
||||||
|
})();
|
||||||
|
// Blend base colour 25% toward white before applying the sweep.
|
||||||
|
const [r,g,b] = baseRgb.map(c => Math.min(255, Math.round(c + (255 - c) * 0.66)));
|
||||||
|
const lighten = (c) => Math.min(255, Math.round(c + (255 - c) * 0.30));
|
||||||
|
const darken = (c) => Math.round(c * 0.93);
|
||||||
|
const light = `rgb(${lighten(r)},${lighten(g)},${lighten(b)})`;
|
||||||
|
const mid = `rgb(${r},${g},${b})`;
|
||||||
|
const dark = `rgb(${darken(r)},${darken(g)},${darken(b)})`;
|
||||||
|
return `linear-gradient(135deg, ${light} 0%, ${mid} 60%, ${dark} 100%)`;
|
||||||
};
|
};
|
||||||
const tempBgStrong = tempBg;
|
const airTempFontColor = () => '#1a1a1a';
|
||||||
const tempFontColor = (t) => {
|
|
||||||
if (t == null) return '#1a1200';
|
|
||||||
const band = utciCategory(t);
|
|
||||||
return band ? band.fg : '#1a1200';
|
|
||||||
};
|
|
||||||
const tempFontColorStrong = tempFontColor;
|
|
||||||
// Returns any extra band styles (fontWeight, textShadow) for a given temp.
|
// Returns any extra band styles (fontWeight, textShadow) for a given temp.
|
||||||
const bandExtras = (t) => {
|
const bandExtras = (t) => {
|
||||||
const band = utciCategory(t);
|
const band = utciCategory(t);
|
||||||
@@ -638,19 +665,19 @@ ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeC
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
${visibleCols.utciP && html`
|
${visibleCols.utciP && html`
|
||||||
<td class=${groupStart('utciP')} style=${{ background: bandGradient(adjCat.bg, adjCat.darkenAmt), color: adjCat.fg, fontSize: '13px', ...bandExtras(r.utciAdj) }}>
|
<td class=${groupStart('utciP')} style=${{ background: airTempBg(r.utciAdj), color: airTempFontColor(r.utciAdj), fontSize: '13px' }}>
|
||||||
${fmt(r.utciAdj)}${u('°C')}
|
${fmt(r.utciAdj)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.vehicleT && html`
|
${visibleCols.vehicleT && html`
|
||||||
<td class=${groupStart('vehicleT')} style=${{ color: tempFontColorStrong(r.vehicleT), background: tempBgStrong(r.vehicleT), ...bandExtras(r.vehicleT) }}>
|
<td class=${groupStart('vehicleT')} style=${{ color: airTempFontColor(r.vehicleT), background: airTempBg(r.vehicleT) }}>
|
||||||
${fmt(r.vehicleT)}${u('°C')}
|
${fmt(r.vehicleT)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${indoorMode === 'on' && !indoorManaged && html`
|
${indoorMode === 'on' && !indoorManaged && html`
|
||||||
<td class=${groupStart('indoorT')} style=${{ color: tempFontColorStrong(r.indoorT), background: tempBgStrong(r.indoorT), ...bandExtras(r.indoorT) }}>
|
<td class=${groupStart('indoorT')} style=${{ color: airTempFontColor(r.indoorT), background: airTempBg(r.indoorT) }}>
|
||||||
${fmt(r.indoorT)}${u('°C')}
|
${fmt(r.indoorT)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${indoorMode === 'on' && indoorManaged && html`
|
${indoorMode === 'on' && indoorManaged && html`
|
||||||
<td class=${groupStart('managedT')} style=${{ color: tempFontColorStrong(r.managedT), background: tempBgStrong(r.managedT), ...bandExtras(r.managedT) }}>
|
<td class=${groupStart('managedT')} style=${{ color: airTempFontColor(r.managedT), background: airTempBg(r.managedT) }}>
|
||||||
${fmt(r.managedT)}${u('°C')}
|
${fmt(r.managedT)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.burn && html`
|
${visibleCols.burn && html`
|
||||||
@@ -658,7 +685,7 @@ ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeC
|
|||||||
${burnLabel(burnMins)}
|
${burnLabel(burnMins)}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.utci && html`
|
${visibleCols.utci && html`
|
||||||
<td class=${groupStart('utci')} style=${{ background: bandGradient(cat.bg, cat.darkenAmt), color: cat.fg, ...bandExtras(r.utci) }}>
|
<td class=${groupStart('utci')} style=${{ background: airTempBg(r.utci), color: airTempFontColor(r.utci) }}>
|
||||||
${fmt(r.utci)}${u('°C')}
|
${fmt(r.utci)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.delta && html`
|
${visibleCols.delta && html`
|
||||||
@@ -668,20 +695,20 @@ ${(isPro ? (activeProfile === 'custom' || activeProfile === 'showall' || activeC
|
|||||||
}}>
|
}}>
|
||||||
${delta > 0 ? '+' : ''}${fmt(delta)}${u('°C')}
|
${delta > 0 ? '+' : ''}${fmt(delta)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.tmrt && html`<td class=${groupStart('tmrt')} style=${{ background: tempBgStrong(r.Tmrt), color: tempFontColorStrong(r.Tmrt), ...bandExtras(r.Tmrt) }}>${fmt(r.Tmrt)}${u('°C')}</td>`}
|
${visibleCols.tmrt && html`<td class=${groupStart('tmrt')} style=${{ background: airTempBg(r.Tmrt), color: airTempFontColor(r.Tmrt) }}>${fmt(r.Tmrt)}${u('°C')}</td>`}
|
||||||
${visibleCols.concreteT && html`
|
${visibleCols.concreteT && html`
|
||||||
<td class=${groupStart('concreteT')} style=${{ color: tempFontColorStrong(r.concreteT), background: tempBgStrong(r.concreteT), ...bandExtras(r.concreteT) }}>
|
<td class=${groupStart('concreteT')} style=${{ color: airTempFontColor(r.concreteT), background: airTempBg(r.concreteT) }}>
|
||||||
${fmt(r.concreteT)}${u('°C')}
|
${fmt(r.concreteT)}${u('°C')}
|
||||||
</td>`}
|
</td>`}
|
||||||
${visibleCols.soilT && html`
|
${visibleCols.soilT && html`
|
||||||
<td class=${groupStart('soilT')} style=${{ color: tempFontColorStrong(r.soilT0), background: tempBgStrong(r.soilT0), ...bandExtras(r.soilT0) }}>${fmt(r.soilT0)}${u('°C')}</td>`}
|
<td class=${groupStart('soilT')} style=${{ color: airTempFontColor(r.soilT0), background: airTempBg(r.soilT0) }}>${fmt(r.soilT0)}${u('°C')}</td>`}
|
||||||
${visibleCols.soilT6 && html`
|
${visibleCols.soilT6 && html`
|
||||||
<td class=${groupStart('soilT6')} style=${{ color: tempFontColorStrong(r.soilT6), background: tempBgStrong(r.soilT6), ...bandExtras(r.soilT6) }}>${fmt(r.soilT6)}${u('°C')}</td>`}
|
<td class=${groupStart('soilT6')} style=${{ color: airTempFontColor(r.soilT6), background: airTempBg(r.soilT6) }}>${fmt(r.soilT6)}${u('°C')}</td>`}
|
||||||
${visibleCols.soilM && html`
|
${visibleCols.soilM && html`
|
||||||
<td class=${groupStart('soilM')} style=${{ color: '#2a6a90', background: scaleBg(r.soilM, 0.12, 0.45, '50,125,190') }}>${r.soilM != null ? fmt(r.soilM * 100, 1) + u('%') : '—'}</td>`}
|
<td class=${groupStart('soilM')} style=${{ color: '#2a6a90', background: scaleBg(r.soilM, 0.12, 0.45, '50,125,190') }}>${r.soilM != null ? fmt(r.soilM * 100, 1) + u('%') : '—'}</td>`}
|
||||||
${visibleCols.air && html`<td class=${groupStart('air')} style=${{ background: tempBg(r.Ta), color: tempFontColorStrong(r.Ta), ...bandExtras(r.Ta) }}>${fmt(r.Ta)}${u('°C')}</td>`}
|
${visibleCols.air && html`<td class=${groupStart('air')} style=${{ background: airTempBg(r.Ta), color: airTempFontColor(r.Ta) }}>${fmt(r.Ta)}${u('°C')}</td>`}
|
||||||
${visibleCols.rh && html`<td class=${groupStart('rh')} style=${{ background: scaleBg(r.RH, 30, 100, '70,145,200') }}>${Math.round(r.RH)}${u('%')}</td>`}
|
${visibleCols.rh && html`<td class=${groupStart('rh')} style=${{ background: scaleBg(r.RH, 30, 100, '70,145,200') }}>${Math.round(r.RH)}${u('%')}</td>`}
|
||||||
${visibleCols.dew && html`<td class=${groupStart('dew')} style=${{ background: tempBgStrong(r.dew), color: tempFontColorStrong(r.dew), ...bandExtras(r.dew) }}>${fmt(r.dew)}${u('°C')}</td>`}
|
${visibleCols.dew && html`<td class=${groupStart('dew')} style=${{ background: airTempBg(r.dew), color: airTempFontColor(r.dew) }}>${fmt(r.dew)}${u('°C')}</td>`}
|
||||||
${visibleCols.precip && html`
|
${visibleCols.precip && html`
|
||||||
<td class=${groupStart('precip')} style=${{ background: r.snow > 0 ? scaleBg(r.snow, 0, 4, '90,140,210') : scaleBg(r.precip, 0, 8, '70,145,200') }}>
|
<td class=${groupStart('precip')} style=${{ background: r.snow > 0 ? scaleBg(r.snow, 0, 4, '90,140,210') : scaleBg(r.precip, 0, 8, '70,145,200') }}>
|
||||||
<span style=${{ display: 'inline-flex', alignItems: 'center', gap: '5px', verticalAlign: 'middle' }}>
|
<span style=${{ display: 'inline-flex', alignItems: 'center', gap: '5px', verticalAlign: 'middle' }}>
|
||||||
|
|||||||
Reference in New Issue
Block a user