1- import { useAutoAnimate } from '@formkit/auto-animate/react' ;
21import { WindIcon } from '@phosphor-icons/react' ;
2+ import { useRef , useEffect , useState } from 'react' ;
33
44export 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