1.9.3
Updated scope temperature arc to gradient Fix banner scaling Add Pulldown to scope
This commit is contained in:
+44
-33
@@ -10,7 +10,7 @@
|
||||
// SkyScope({ elev, dt, glob, size }) small porthole per hour
|
||||
// WindVane({ bearing, size }) compass-arrow widget
|
||||
// CloudIcon({ category, size, elev, dt }) cloud/sun glyph
|
||||
// ScopeReticle({ value, cat, loading, elev, dt, glob, activeEvent })
|
||||
// ScopeReticle({ value, cat, loading, elev, dt, glob, activeEvent, utciEnvShort })
|
||||
// large UTCI dial
|
||||
// PrecipIcon({ precip, snow, size }) rain/snow icon
|
||||
// ------------------------------------------------------------------------
|
||||
@@ -92,6 +92,7 @@ export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel,
|
||||
onClick=${(e) => { e.stopPropagation(); setOpen(o => !o); }}
|
||||
type="button"
|
||||
>
|
||||
<span class="cs-btn-overlay"></span>
|
||||
<span class="cs-btn-label">${btnLabel}</span>
|
||||
<span class="cs-arrow"></span>
|
||||
</button>
|
||||
@@ -454,32 +455,39 @@ export function ScopeReticle({ value, cat, loading, elev = 0, dt = new Date(), g
|
||||
major, medium,
|
||||
};
|
||||
});
|
||||
const stressBands = [
|
||||
{ min: -40, max: -27, color: '#5a9bdc' },
|
||||
{ min: -27, max: -13, color: '#5a9bdc' },
|
||||
{ min: -13, max: 0, color: '#6ca9e1' },
|
||||
{ min: 0, max: 9, color: '#93ccd9' },
|
||||
{ min: 9, max: 18, color: '#92d4a3' },
|
||||
{ min: 18, max: 26, color: '#dae15f' },
|
||||
{ min: 26, max: 32, color: '#f8a13f' },
|
||||
{ min: 32, max: 38, color: '#e15333' },
|
||||
{ min: 38, max: 46, color: '#ae181c' },
|
||||
{ min: 46, max: 50, color: '#8d0616' },
|
||||
];
|
||||
function fracToXY(frac, r) {
|
||||
const deg = 135 + frac * 270;
|
||||
const rad = (deg * Math.PI) / 180;
|
||||
return [cx + r * Math.cos(rad), cy + r * Math.sin(rad)];
|
||||
}
|
||||
function bandArcPath(band) {
|
||||
const f1 = Math.min(1, Math.max(0, (band.min + 10) / 60));
|
||||
const f2 = Math.min(1, Math.max(0, (band.max + 10) / 60));
|
||||
const arcR = R - 18;
|
||||
// Gradient colour stops: frac 0 = −10 °C, frac 1 = 50 °C
|
||||
const ARC_GRAD = [
|
||||
[0, [106, 169, 225]],
|
||||
[0.167, [147, 204, 217]],
|
||||
[0.317, [146, 212, 163]],
|
||||
[0.467, [218, 225, 95]],
|
||||
[0.600, [248, 161, 63]],
|
||||
[0.700, [225, 83, 51]],
|
||||
[0.800, [174, 24, 28]],
|
||||
[1.000, [141, 6, 22]],
|
||||
];
|
||||
function arcColorAt(f) {
|
||||
for (let i = 0; i < ARC_GRAD.length - 1; i++) {
|
||||
const [f1, c1] = ARC_GRAD[i], [f2, c2] = ARC_GRAD[i + 1];
|
||||
if (f <= f2) {
|
||||
const t = (f - f1) / (f2 - f1);
|
||||
return `rgb(${Math.round(c1[0]+(c2[0]-c1[0])*t)},${Math.round(c1[1]+(c2[1]-c1[1])*t)},${Math.round(c1[2]+(c2[2]-c1[2])*t)})`;
|
||||
}
|
||||
}
|
||||
return 'rgb(141,6,22)';
|
||||
}
|
||||
const arcR = R - 18;
|
||||
const gradArc = Array.from({ length: 90 }, (_, i) => {
|
||||
const f1 = i / 90, f2 = (i + 1) / 90;
|
||||
const [x1, y1] = fracToXY(f1, arcR);
|
||||
const [x2, y2] = fracToXY(f2, arcR);
|
||||
const large = (f2 - f1) * 270 > 180 ? 1 : 0;
|
||||
return `M ${x1} ${y1} A ${arcR} ${arcR} 0 ${large} 1 ${x2} ${y2}`;
|
||||
}
|
||||
return { d: `M ${x1} ${y1} A ${arcR} ${arcR} 0 0 1 ${x2} ${y2}`, color: arcColorAt((f1+f2)/2) };
|
||||
});
|
||||
let needleX = cx, needleY = cy + 54;
|
||||
if (value != null) {
|
||||
const frac = Math.min(1, Math.max(0, (value + 10) / 60));
|
||||
@@ -569,9 +577,9 @@ export function ScopeReticle({ value, cat, loading, elev = 0, dt = new Date(), g
|
||||
if (!overlaySVG) return null;
|
||||
return html`<g dangerouslySetInnerHTML=${{ __html: overlaySVG }} />`;
|
||||
})()}
|
||||
${stressBands.map((b, i) => html`
|
||||
<path key=${i} d=${bandArcPath(b)} fill="none"
|
||||
stroke=${b.color} stroke-width="4" stroke-linecap="butt" />`)}
|
||||
${gradArc.map((seg, i) => html`
|
||||
<path key=${i} d=${seg.d} fill="none"
|
||||
stroke=${seg.color} stroke-width="4" stroke-linecap="butt" />`)}
|
||||
<circle cx=${cx} cy=${cy} r=${R} fill="none" stroke="#c9b08a" stroke-width="1.5" />
|
||||
${ticks.map((t, i) => html`
|
||||
<line key=${i} x1=${t.x1} y1=${t.y1} x2=${t.x2} y2=${t.y2}
|
||||
@@ -621,23 +629,26 @@ export function ScopeReticle({ value, cat, loading, elev = 0, dt = new Date(), g
|
||||
font-family="Fraunces, serif" font-weight="700">
|
||||
${value.toFixed(1)}°
|
||||
</text>
|
||||
<text x=${cx} y=${cy + 15} text-anchor="middle"
|
||||
fill=${readoutMutedColor} font-size="6.5"
|
||||
<text x=${cx} y=${cy + 14} text-anchor="middle"
|
||||
fill=${readoutColor} font-size="8"
|
||||
font-family="Manrope, sans-serif" font-weight="700" letter-spacing="1.2">
|
||||
UTCI NOW
|
||||
SUNSOAK INDEX
|
||||
</text>
|
||||
<text x=${cx} y=${cy + 23} text-anchor="middle"
|
||||
fill=${glowColor} font-size="7"
|
||||
fill=${glowColor} font-size="9"
|
||||
font-family="Manrope, sans-serif" font-weight="700" letter-spacing="0.5">
|
||||
${cat.label.toUpperCase()}
|
||||
</text>
|
||||
${utciEnvShort && html`
|
||||
<text x=${cx} y="163" text-anchor="middle"
|
||||
fill=${readoutMutedColor} font-size="5.5"
|
||||
font-family="Manrope, sans-serif" font-weight="700" letter-spacing="0.8"
|
||||
opacity="0.85">
|
||||
${utciEnvShort.toUpperCase()} EST.
|
||||
</text>`}
|
||||
<${Fragment}>
|
||||
<rect x=${cx - 34} y="158" width="68" height="11" rx="3"
|
||||
fill=${glowColor} opacity="0.22" />
|
||||
<text x=${cx} y="166" text-anchor="middle"
|
||||
fill=${readoutColor} font-size="7"
|
||||
font-family="Manrope, sans-serif" font-weight="700" letter-spacing="0.6">
|
||||
${utciEnvShort.toUpperCase()}
|
||||
</text>
|
||||
</>`}
|
||||
</>`
|
||||
: html`<text x=${cx} y=${cy + 5} text-anchor="middle"
|
||||
fill=${readoutMutedColor} font-size="8"
|
||||
|
||||
Reference in New Issue
Block a user