From fc6fea9cfbca252e862016c323ed485a38de8460 Mon Sep 17 00:00:00 2001 From: Alvaro Date: Fri, 4 Oct 2024 12:58:55 +0200 Subject: [PATCH] Update marker popups --- public/icons/arrow-right.svg | 3 ++ public/icons/close.svg | 3 ++ src/components/globe/camera.tsx | 33 ++++++++++--- src/components/globe/index.tsx | 7 +-- src/components/globe/marker.tsx | 85 ++++++++++++++++++++++++++++++--- 5 files changed, 115 insertions(+), 16 deletions(-) create mode 100644 public/icons/arrow-right.svg create mode 100644 public/icons/close.svg diff --git a/public/icons/arrow-right.svg b/public/icons/arrow-right.svg new file mode 100644 index 0000000..b702ac2 --- /dev/null +++ b/public/icons/arrow-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/icons/close.svg b/public/icons/close.svg new file mode 100644 index 0000000..2865f49 --- /dev/null +++ b/public/icons/close.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/globe/camera.tsx b/src/components/globe/camera.tsx index f33edd7..aec4034 100644 --- a/src/components/globe/camera.tsx +++ b/src/components/globe/camera.tsx @@ -1,29 +1,48 @@ -import { useState } from "react"; +import { useState, useEffect, useMemo } from "react"; import { CameraControls } from "@react-three/drei"; -import { useThree, useFrame } from "@react-three/fiber" +import { useThree, RootState } from "@react-three/fiber" import { useRef } from "react"; import { convertLatLonToGlobalPosition } from "@/lib/globe-utils"; import type { MarkerType } from "./marker"; +import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'; + export const Camera = ({ marker }: { marker: MarkerType | undefined }) => { const cameraControlsRef = useRef(null!); const [resetControls, setResetControls] = useState(true); + const canvasElement = useMemo(() => document.getElementsByTagName('canvas')[0], [document]); + + useEffect(() => { + if (marker === undefined) { + setResetControls(true); + } + }, [marker]); + + const controls = useThree((state: RootState) => (state.controls as OrbitControls)); - useThree(({ controls }) => { + useEffect(() => { + if (!controls) return; if (controls) { if (marker !== undefined) { - cameraControlsRef.current.setPosition(...convertLatLonToGlobalPosition(marker.lat, marker.lng, 2), true); + const [x, y, z] = convertLatLonToGlobalPosition(marker.lat, marker.lng, 2); + controls.disconnect() + cameraControlsRef.current.setPosition(x, y, z, true); } if (resetControls) { - cameraControlsRef.current.setPosition(0, 1, 4); - cameraControlsRef.current.setTarget(0, 0, 0); + if (controls) { + controls.connect(canvasElement) + } + if (cameraControlsRef.current) { + cameraControlsRef.current.setPosition(0, 1, 4, true); + cameraControlsRef.current.setTarget(0, 0, 0, true); + } setResetControls(false); } } - }); + }), [marker, resetControls, controls, canvasElement]; return ( (null); - const marker = selectedMarker ? markers.find(m => m.id === selectedMarker) : undefined; + const [selectedMarker, setSelectedMarker] = useState(null); + + const marker = selectedMarker !== null ? markers[selectedMarker] : undefined; return ( <>
{markers.map((marker, index) => ( - + Click to explore the phenomenon ))} diff --git a/src/components/globe/marker.tsx b/src/components/globe/marker.tsx index d330b22..7dfe93c 100644 --- a/src/components/globe/marker.tsx +++ b/src/components/globe/marker.tsx @@ -3,12 +3,81 @@ import { useState, useRef } from 'react' import { useFrame } from '@react-three/fiber' import { Html } from '@react-three/drei' import { convertLatLonToVec3 } from "@/lib/globe-utils"; +import Image from 'next/image'; -function Marker({ id, lat, lng, children, setSelectedMarker, ...props }: { +const Popup = ({ setSelectedMarker, index }: { + setSelectedMarker: + (index: number | null) => void + index: number +}) => { + return ( +
+
+
+
+ +
+
+
+
+
+
+
+
Amazon. Brazil
+
Diurnal precipitation cycle
+
+
+ + +
+
+
+
+
LOW (0 m³/m²)
+
HIGH (0.1 m³/m²)
+
+
+
+
+
+
+
+
The diurnal precipitation cycle over the Amazon rainforest highlights the complex interactions and feedbacks between atmosphere and land. The diurnal rainfall, maintained by moisture inflow from the Atlantic ocean into the Amazon basin, arises due to evapotranspiration and moisture recycling from the dense forest. This self-sustained cycle is in turn driven by sharp contrasts in temperature between day and night.
+
+
+
+
+
+
+
+
+
+
+
+ +
+ ); +} +function Marker({ id, index, lat, lng, children, setSelectedMarker, isSelected, ...props }: { id: string + index: number lat: number lng: number - setSelectedMarker: (id: string) => void, + setSelectedMarker: (index: number | null) => void, + isSelected: boolean, children: React.ReactNode }) { const ref = useRef(null) @@ -23,6 +92,7 @@ function Marker({ id, lat, lng, children, setSelectedMarker, ...props }: { const range = state.camera.position.distanceTo(ref.current.getWorldPosition(vec)) <= 10 if (range !== isInRange) setInRange(range) }) + return ( -
setSelectedMarker(id)} - >
- {!!children &&
{children}
} + {isSelected ? : + <>
setSelectedMarker(index)} + >
+ {!!children &&
{children}
} + + }
)