diff --git a/client/public/countries.geojson b/client/public/countries.geojson index 8b08c62..b094924 100644 --- a/client/public/countries.geojson +++ b/client/public/countries.geojson @@ -20209,28 +20209,6 @@ [21.268449, 55.190482] ] ], - [ - [ - [33.435988, 45.971917], - [33.699462, 46.219573], - [34.410402, 46.005162], - [34.732017, 45.965666], - [34.861792, 45.768182], - [35.012659, 45.737725], - [35.020788, 45.651219], - [35.510009, 45.409993], - [36.529998, 45.46999], - [36.334713, 45.113216], - [35.239999, 44.939996], - [33.882511, 44.361479], - [33.326421, 44.564877], - [33.546924, 45.034771], - [32.454174, 45.327466], - [32.630804, 45.519186], - [33.588162, 45.851569], - [33.435988, 45.971917] - ] - ], [ [ [143.648007, 50.7476], @@ -24180,10 +24158,17 @@ [35.823685, 46.645964], [34.962342, 46.273197], [35.012659, 45.737725], - [34.861792, 45.768182], - [34.732017, 45.965666], - [34.410402, 46.005162], - [33.699462, 46.219573], + [35.020788, 45.651219], + [35.510009, 45.409993], + [36.529998, 45.46999], + [36.334713, 45.113216], + [35.239999, 44.939996], + [33.882511, 44.361479], + [33.326421, 44.564877], + [33.546924, 45.034771], + [32.454174, 45.327466], + [32.630804, 45.519186], + [33.588162, 45.851569], [33.435988, 45.971917], [33.298567, 46.080598], [31.74414, 46.333348], diff --git a/client/src/app/[site]/realtime/RealtimeGlobe/RealtimeGlobe.tsx b/client/src/app/[site]/realtime/RealtimeGlobe/RealtimeGlobe.tsx index efbe062..6106512 100644 --- a/client/src/app/[site]/realtime/RealtimeGlobe/RealtimeGlobe.tsx +++ b/client/src/app/[site]/realtime/RealtimeGlobe/RealtimeGlobe.tsx @@ -4,8 +4,8 @@ import { useQuery } from "@tanstack/react-query"; import { useWindowSize } from "@uidotdev/usehooks"; import { scaleSequentialSqrt } from "d3-scale"; import { interpolateYlOrRd } from "d3-scale-chromatic"; -import { memoize } from "lodash"; -import { useEffect, useMemo, useRef } from "react"; +import { memoize, debounce } from "lodash"; +import { useEffect, useMemo, useRef, useState, useCallback } from "react"; import Globe from "react-globe.gl"; import { MeshPhongMaterial } from "three"; import { useGetLiveSessionLocations } from "../../../../api/analytics/useGetLiveSessionLocations"; @@ -53,6 +53,44 @@ export const World = ({ width }: { width: number }) => { } }, [globeEl.current]); + const [hexAltitude, setHexAltitude] = useState(0.001); + + // Debounced updateAltitude handler: fires once, 200ms after the last 'end' event + const updateAltitude = useCallback( + debounce(() => { + if (!globeEl.current) return; + + const controls = globeEl.current.controls(); + const distance = Math.round(controls.getDistance()); + + const low = 0.001, mid = 0.005, high = 0.02; + const near = 300, far = 600; + const nextAlt = + distance <= near ? low : + distance >= far ? high : + mid; + + // set only if changed + if (nextAlt !== hexAltitude) { + setHexAltitude(nextAlt); + } + }, 200), + [globeEl, hexAltitude, setHexAltitude] + ); + + useEffect(() => { + if (!globeEl.current) return; + const controls = globeEl.current.controls(); + // Limit distance maximal distance + controls.maxDistance = 900; + // Subscribe on change event + controls.addEventListener('end', updateAltitude); + return () => { + controls.removeEventListener('end', updateAltitude); + updateAltitude.cancel(); // cancel any pending call + }; + }, [globeEl, updateAltitude]); + const oceanBlueMaterial = useMemo( () => new MeshPhongMaterial({ @@ -106,6 +144,7 @@ export const World = ({ width }: { width: number }) => { hexPolygonMargin={0.2} hexBinResolution={3} hexBinPointsData={liveSessionLocationsData} + hexPolygonAltitude={hexAltitude} hexBinMerge={true} hexBinPointWeight={"count"} backgroundColor="rgba(0, 0, 0, 0)" diff --git a/client/src/app/[site]/realtime/page.tsx b/client/src/app/[site]/realtime/page.tsx index e9fcc97..fac5448 100644 --- a/client/src/app/[site]/realtime/page.tsx +++ b/client/src/app/[site]/realtime/page.tsx @@ -33,7 +33,6 @@ export default function RealtimePage() { return (