Skip to content

Commit 65f733f

Browse files
authored
fix: make sure weather direction to animate the shortest path (#40)
1 parent 2660e17 commit 65f733f

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

src/frontend/components/Standings/Relative.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export const Relative = () => {
7373

7474
return (
7575
<div
76-
className="w-full h-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2"
76+
className="w-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2"
7777
style={{
7878
['--bg-opacity' as string]: `${config?.background?.opacity ?? 0}%`,
7979
}}

src/frontend/components/Standings/Standings.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const Standings = () => {
1919
const settings = useStandingsSettings();
2020
return (
2121
<div
22-
className={`w-full h-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2 text-white overflow-hidden`}
22+
className={`w-full bg-slate-800/[var(--bg-opacity)] rounded-sm p-2 text-white overflow-hidden`}
2323
style={{
2424
['--bg-opacity' as string]: `${settings?.background?.opacity ?? 0}%`,
2525
}}

src/frontend/components/Weather/Weather.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { WeatherTrackRubbered } from './WeatherTrackRubbered/WeatherTrackRubbere
77
import { WindDirection } from './WindDirection/WindDirection';
88
import { useTrackRubberedState } from './hooks/useTrackRubberedState';
99
import { useWeatherSettings } from './hooks/useWeatherSettings';
10+
import { useTelemetryValue } from '@irdashies/context';
1011

1112
export const Weather = () => {
1213
const [parent] = useAutoAnimate();
@@ -16,6 +17,7 @@ export const Weather = () => {
1617
const relativeWindDirection = (weather.windDirection ?? 0) - (weather.windYaw ?? 0);
1718
const trackRubbered = useTrackRubberedState();
1819
const settings = useWeatherSettings();
20+
const unit = useTelemetryValue('DisplayUnits');
1921

2022
return (
2123
<div
@@ -28,7 +30,7 @@ export const Weather = () => {
2830
<div className="flex flex-col p-2 w-full rounded-sm gap-2">
2931
<WeatherTemp title="Track" value={trackTemp.trackTemp} />
3032
<WeatherTemp title="Air" value={trackTemp.airTemp} />
31-
<WindDirection speedMs={windSpeed} direction={relativeWindDirection} />
33+
<WindDirection speedMs={windSpeed} direction={relativeWindDirection} metric={unit === 1} />
3234
<WeatherTrackWetness trackMoisture={weather.trackMoisture} />
3335
<WeatherTrackRubbered trackRubbered={trackRubbered} />
3436
</div>

src/frontend/components/Weather/WindDirection/WindDirection.tsx

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,44 @@
1-
import { useAutoAnimate } from '@formkit/auto-animate/react';
21
import { WindIcon } from '@phosphor-icons/react';
2+
import { useRef, useEffect, useState } from 'react';
33

44
export interface WindDirectionProps {
55
speedMs?: number;
66
direction?: number;
7+
metric?: boolean;
78
}
89

9-
export const WindDirection = ({ speedMs, direction }: WindDirectionProps) => {
10-
const speed = speedMs !== undefined ? speedMs * (18 / 5) : undefined;
11-
const [parent] = useAutoAnimate();
10+
export const WindDirection = ({
11+
speedMs,
12+
direction,
13+
metric = true,
14+
}: WindDirectionProps) => {
15+
// Convert m/s to user's preferred unit
16+
const speed =
17+
speedMs !== undefined
18+
? speedMs * (metric ? 3.6 : 2.23694) // km/h or mph
19+
: undefined;
20+
21+
const [normalizedAngle, setNormalizedAngle] = useState<number>(0);
22+
const prevAngleRef = useRef<number>(0);
23+
24+
useEffect(() => {
25+
if (direction === undefined) return;
26+
27+
const currentAngle = direction;
28+
const prevAngle = prevAngleRef.current;
29+
30+
// Calculate the shortest path difference
31+
let diff = currentAngle - prevAngle;
32+
33+
// Normalize to [-π, π] range
34+
while (diff > Math.PI) diff -= 2 * Math.PI;
35+
while (diff < -Math.PI) diff += 2 * Math.PI;
36+
37+
// Update the normalized angle
38+
setNormalizedAngle((prev) => prev + diff);
39+
prevAngleRef.current = currentAngle;
40+
}, [direction]);
41+
1242
return (
1343
<div className="bg-slate-800/70 p-2 rounded-sm">
1444
<div className="flex flex-row gap-x-2 items-center text-sm mb-3">
@@ -17,21 +47,20 @@ export const WindDirection = ({ speedMs, direction }: WindDirectionProps) => {
1747
</div>
1848
<div
1949
id="wind"
20-
ref={parent}
2150
className="flex aspect-square relative w-full max-w-[120px] mx-auto"
2251
>
2352
<svg
2453
xmlns="http://www.w3.org/2000/svg"
2554
viewBox="0 0 60 60"
2655
className="absolute stroke-current stroke-[3] w-full h-full box-border fill-none origin-center transform-gpu transition-transform duration-1000 ease-out"
2756
style={{
28-
rotate: `calc(${direction ?? 0} * 1rad + 0.5turn)`,
57+
rotate: `calc(${normalizedAngle} * 1rad + 0.5turn)`,
2958
}}
3059
>
3160
<path d="M48 8A28 28 90 0158 30c0 15.464-12.536 28-28 28S2 45.464 2 30A28 28 90 0112 8M22 9 30 1l8 8" />
3261
</svg>
3362
<div className="absolute w-full h-full flex justify-center items-center text-[32px]">
34-
{speed !== undefined ? speed.toFixed(1) : '-'}
63+
{speed !== undefined ? Math.round(speed) : '-'}
3564
</div>
3665
</div>
3766
</div>

0 commit comments

Comments
 (0)