1
1
"use client"
2
2
3
- import { useEffect , useMemo , useRef , useState } from "react"
3
+ import { useCallback , useEffect , useMemo , useRef , useState } from "react"
4
4
import { useTheme } from "next-themes"
5
5
import Globe from "react-globe.gl"
6
6
import { type GlobeMethods } from "react-globe.gl"
@@ -12,6 +12,7 @@ import Link from "@/components/ui/Link"
12
12
import countries from "./countries.json"
13
13
14
14
import { useBreakpointValue } from "@/hooks/useBreakpointValue"
15
+ import { usePrefersReducedMotion } from "@/hooks/usePrefersReducedMotion"
15
16
import EthLogo from "@/public/images/assets/eth-glyph-colored.png"
16
17
17
18
// Define a type for event data
@@ -42,6 +43,7 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
42
43
const globeRef = useRef < GlobeMethods > ( )
43
44
const globeContainerRef = useRef < HTMLDivElement > ( null )
44
45
const { resolvedTheme } = useTheme ( )
46
+ const { prefersReducedMotion } = usePrefersReducedMotion ( )
45
47
46
48
const atmosphereColor = resolvedTheme === "dark" ? "#B38DF0" : "#945AF4"
47
49
@@ -61,7 +63,7 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
61
63
const b = Math . min ( 255 , Math . floor ( ( basePurple & 0xff ) * 1.3 ) )
62
64
return `#${ r . toString ( 16 ) . padStart ( 2 , "0" ) } ${ g . toString ( 16 ) . padStart ( 2 , "0" ) } ${ b . toString ( 16 ) . padStart ( 2 , "0" ) } `
63
65
} )
64
- } , [ countries . features , resolvedTheme ] )
66
+ } , [ resolvedTheme ] )
65
67
66
68
const hexPolygonColor = ( feature : object ) => {
67
69
const idx = countries . features . indexOf (
@@ -78,10 +80,18 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
78
80
return hexPolygonColors [ idx ]
79
81
}
80
82
83
+ // Function to safely set auto-rotate based on motion preferences
84
+ const setAutoRotate = useCallback (
85
+ ( controls : ExtendedOrbitControls , value : boolean ) => {
86
+ controls . autoRotate = value && ! prefersReducedMotion
87
+ } ,
88
+ [ prefersReducedMotion ]
89
+ )
90
+
81
91
useEffect ( ( ) => {
82
92
if ( globeRef . current ) {
83
93
const controls = globeRef . current . controls ( ) as ExtendedOrbitControls
84
- controls . autoRotate = true
94
+ setAutoRotate ( controls , true )
85
95
controls . enablePan = false
86
96
controls . enableZoom = false
87
97
controls . autoRotateSpeed = 2.0
@@ -90,7 +100,7 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
90
100
const ambientLight = new THREE . AmbientLight ( 0xffffff , 1 )
91
101
globeRef . current . scene ( ) . add ( ambientLight )
92
102
}
93
- } , [ ] )
103
+ } , [ setAutoRotate ] )
94
104
95
105
// Prepare htmlElementsData for EthLogo
96
106
const htmlElementsData = events . map ( ( event ) => ( {
@@ -176,7 +186,7 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
176
186
}
177
187
// Stop rotation immediately
178
188
const controls = globeRef . current . controls ( ) as ExtendedOrbitControls
179
- controls . autoRotate = false
189
+ setAutoRotate ( controls , false )
180
190
if ( "autoRotateSpeed" in controls ) controls . autoRotateSpeed = 0
181
191
if ( controls . _sphericalDelta ) {
182
192
controls . _sphericalDelta . theta = 0
@@ -193,15 +203,15 @@ const TenYearGlobe = ({ events }: { events: EventData[] }) => {
193
203
if ( globeRef . current ) {
194
204
const controls =
195
205
globeRef . current . controls ( ) as ExtendedOrbitControls
196
- controls . autoRotate = true
206
+ setAutoRotate ( controls , true )
197
207
if ( "autoRotateSpeed" in controls ) controls . autoRotateSpeed = 2.0
198
208
}
199
209
}
200
210
} }
201
211
onPointClick = { ( ) => {
202
212
if ( globeRef . current ) {
203
213
const controls = globeRef . current . controls ( ) as ExtendedOrbitControls
204
- controls . autoRotate = false
214
+ setAutoRotate ( controls , false )
205
215
if ( "autoRotateSpeed" in controls ) controls . autoRotateSpeed = 0
206
216
if ( controls . _sphericalDelta ) {
207
217
controls . _sphericalDelta . theta = 0
0 commit comments