Skip to content

Commit

Permalink
Fix globe edge cases
Browse files Browse the repository at this point in the history
  • Loading branch information
Bluesmile82 committed Nov 6, 2024
1 parent cb7caed commit efb3bb3
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 43 deletions.
15 changes: 13 additions & 2 deletions src/components/energy/section-2/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
'use client';

import { useRef, useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import { AnimatePresence, motion } from "framer-motion";
import ScrollStep from "@/components/scroll-step";
import GlobeMap from '@/components/globe-map';
import { useRecoilState } from "recoil";
import { globePhaseAtom } from "@/store";

const transition = { duration: 0.2, ease: 'linear' };

export default function Section2() {
const scrollSectionRef = useRef<HTMLDivElement>(null);
const [step, setStep] = useState('section-2-step-1');
const [globePhase, setGlobePhase] = useRecoilState(globePhaseAtom);

useEffect(() => {
if (globePhase !== 1 && step === 'section-2-step-2') {
setGlobePhase(1);
}
if (globePhase !== 0 && step !== 'section-2-step-2') {
setGlobePhase(0);
}
}, [step, globePhase, setGlobePhase]);

return (
<section className="relative bg-green-200 text-green-700" id="section-2">
Expand All @@ -22,7 +34,6 @@ export default function Section2() {
<GlobeMap
className="h-full w-full"
videoMaterial={step === 'section-2-step-2' ? "videos/capacity_factor_10km.webm" : "videos/wind_speed_global_10km.webm"}
globePhase={step === 'section-2-step-2' ? 5 : 4}
rotate={step !== 'section-2-step-2'}
/>
</div>
Expand Down
94 changes: 61 additions & 33 deletions src/components/globe-map/controls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,32 @@ import type { MarkerType } from "./marker";
import { Group } from "three";
import { useIsMobile } from "@/lib/hooks";
import { useInView } from "framer-motion";
import { useRecoilState } from "recoil";
import { globePhaseAtom } from "@/store";
import { usePathname } from 'next/navigation'

const MADRID_COORDINATES = { lat: 40.416775, lng: -3.703790 };

export const Controls = ({ marker, active = false, enabled = false, groupRef, resetSelectedMarker, setEnabled, globePhase, canvasRef }: {
const ZOOMS = {
'home': {
'initial': {
'mobile': 2.8,
'desktop': 2.8
},
'phase3': {
'mobile': 4,
'desktop': 4
}
},
'energy': {
'initial': {
'mobile': 4.5,
'desktop': 4.75
}
}
};

export const Controls = ({ marker, active = false, enabled = false, groupRef, resetSelectedMarker, setEnabled, canvasRef }: {
marker: MarkerType | undefined
// Active is used to determine if the globe controls are in a phase that could be enabled even if is temporarily disabled
active: boolean
Expand All @@ -18,42 +40,46 @@ export const Controls = ({ marker, active = false, enabled = false, groupRef, re
setEnabled: (enabled: boolean) => void
groupRef: React.MutableRefObject<Group>
resetSelectedMarker: () => void,
globePhase: number,
canvasRef: React.RefObject<HTMLCanvasElement>
}) => {
const pathname = usePathname()
const isEnergyPage = useMemo(() => pathname === '/case-study-energy', [pathname])

const [globePhase] = useRecoilState(globePhaseAtom);
const isMobile = useIsMobile();
const cameraControlsRef = useRef<CameraControls>(null!);
const [resettingPosition, setResettingPosition] = useState(false);

const resetPosition = () => {
groupRef.current.rotation.y = 0;
if (globePhase === 4) {
cameraControlsRef.current.setPosition(0, 1, isMobile ? 4.5 : 4, true);
cameraControlsRef.current.setTarget(0, 0, 0, true);
return;
}

if (globePhase === 5) {
// Position tooltip in europe
const [x, y, z] = convertLatLonToGlobalPosition(MADRID_COORDINATES.lat, MADRID_COORDINATES.lng, isMobile ? 4.5 : 4);

cameraControlsRef.current.setTarget(0, 0, 0, true);
cameraControlsRef.current.setPosition(x, y, z, true)
return;
}
if (isEnergyPage) {
if (globePhase === 0) {
cameraControlsRef.current.setPosition(0, 1, isMobile ? ZOOMS.energy.initial.mobile : ZOOMS.energy.initial.desktop, true);
cameraControlsRef.current.setTarget(0, 0, 0, true);
return;
}

if (globePhase < 2) {
cameraControlsRef.current.setPosition(0, 1, 2.8, true);
cameraControlsRef.current.setTarget(0, 0.4, 0, true);
if (globePhase === 1) {
// Position tooltip in europe
const [x, y, z] = convertLatLonToGlobalPosition(MADRID_COORDINATES.lat, MADRID_COORDINATES.lng, isMobile ? ZOOMS.energy.initial.mobile : ZOOMS.energy.initial.desktop);
cameraControlsRef.current.setPosition(x, y, z, true)
cameraControlsRef.current.setTarget(0, 0, 0, true);
return;
}
} else {
cameraControlsRef.current.setPosition(0, 1, 4, true);
cameraControlsRef.current.setTarget(0, 0, 0, true);
}
};
if (globePhase < 2) {
cameraControlsRef.current.setPosition(0, 1, isMobile ? ZOOMS.home.initial.mobile : ZOOMS.home.initial.mobile, true);
cameraControlsRef.current.setTarget(0, 0.4, 0, true);
} else {
cameraControlsRef.current.setPosition(0, 1, isMobile ? ZOOMS.home.phase3.mobile : ZOOMS.home.phase3.mobile, true);
cameraControlsRef.current.setTarget(0, 0, 0, true);
}
};
}


useEffect(() => {
if (globePhase === 0 || globePhase === 1 || globePhase === 4 || globePhase === 5) {
if (globePhase === 0 || globePhase === 1) {
resetPosition();
}
}, [globePhase]);
Expand All @@ -77,29 +103,31 @@ export const Controls = ({ marker, active = false, enabled = false, groupRef, re
}
}

// If globephase is 1 and the marker is not active, reset the position
if (!active && marker !== undefined && !resettingPosition) {
setResettingPosition(true);
}

if (resettingPosition) {
groupRef.current.rotation.y = 0;
cameraControlsRef.current.setTarget(0, 0, 0, true);
cameraControlsRef.current.setPosition(0, 1, 4.9, true).then(() => {
cameraControlsRef.current.setTarget(0, 0.4, 0, true);
cameraControlsRef.current.setPosition(0, 1, isMobile ? ZOOMS.home.initial.mobile : ZOOMS.home.initial.desktop, true).then(() => {
setResettingPosition(false);
resetSelectedMarker();
setEnabled(false);
if (globePhase === 2) {
// Scrolling past the globe
resetSelectedMarker();
}
});
}
}, [enabled, marker, active, resettingPosition]);

const isInView = useInView(canvasRef);

useEffect(() => {
// Reset the globe when we pass the globe phase 2
if (!isInView && globePhase === 2 && marker !== undefined) {
setResettingPosition(true);
groupRef.current.rotation.y = 0;
cameraControlsRef.current.setTarget(0, 0, 0, true);
cameraControlsRef.current.setPosition(0, 1, isMobile ? ZOOMS.home.phase3.mobile : ZOOMS.home.phase3.desktop, true).then(() => {
resetSelectedMarker();
setEnabled(true);
});
}
}), [isInView];

Expand Down
7 changes: 3 additions & 4 deletions src/components/globe-map/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use client';
import { useState, useRef, useEffect, CSSProperties, useCallback } from 'react';
import { useState, useRef, useEffect, CSSProperties, useCallback, use } from 'react';
import { Canvas } from '@react-three/fiber'
import { Group } from "three";
import { Controls } from './controls';
Expand All @@ -8,14 +8,13 @@ import GlobeGroup from './globe-group';
import { useGesture } from '@use-gesture/react';
import { useErrorBoundary } from 'use-error-boundary'

export default function GlobeMap({ videoMaterial, className, style, hasMarkers = false, globePhase, rotate = false }:
export default function GlobeMap({ videoMaterial, className, style, hasMarkers = false, rotate = false }:
{
videoMaterial?: string,
className: string,
style?: CSSProperties,
hasMarkers?: boolean,
rotate?: boolean,
globePhase: number
}
) {
const [selectedMarker, setSelectedMarker] = useState<number | null>(null);
Expand Down Expand Up @@ -105,7 +104,7 @@ export default function GlobeMap({ videoMaterial, className, style, hasMarkers =
onWheel={onWheel}
onDrag={onDrag}
>
<Controls canvasRef={canvasRef} marker={marker} active={hasMarkers} enabled={enabled} setEnabled={setEnabled} groupRef={groupRef} resetSelectedMarker={resetSelectedMarker} globePhase={globePhase} />
<Controls canvasRef={canvasRef} marker={marker} active={hasMarkers} enabled={enabled} setEnabled={setEnabled} groupRef={groupRef} resetSelectedMarker={resetSelectedMarker} />
<GlobeGroup
groupRef={groupRef}
hasMarkers={hasMarkers}
Expand Down
7 changes: 3 additions & 4 deletions src/components/home/section-2/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import { useIsMobile } from '@/lib/hooks';
import InfoPopover from '../../info-popover';
import ArrowRight from '@/svgs/arrow-right.svg';
import { useGesture } from "@use-gesture/react";
import { useRecoilState } from "recoil";
import { globePhaseAtom } from "@/store";

const ResizeButton = () => (
<>
Expand Down Expand Up @@ -42,8 +44,7 @@ export default function Section2() {
const isMobile = useIsMobile();

const [initial, setInitial] = useState(true);
const [globePhase, setGlobePhase] = useState(0);

const [globePhase, setGlobePhase] = useRecoilState(globePhaseAtom);
const screenWidth = useScreenWidthWithResize();
const [resizableWidth, setResizableWidth] = useState(screenWidth ? screenWidth / 2 : 800);
const isInView = useInView(scrollSectionRef);
Expand Down Expand Up @@ -195,7 +196,6 @@ export default function Section2() {
})}
videoMaterial="videos/wind_speed_global_10km.webm"
style={{ width: screenWidth }}
globePhase={globePhase}
/>
<div className="absolute inset-0 w-full z-30">
<Resizable
Expand Down Expand Up @@ -226,7 +226,6 @@ export default function Section2() {
videoMaterial={
globePhase === 0 ? "videos/wind_speed_global_100km.webm" : (globePhase === 1 ? "videos/wind_speed_global_10km.webm" : undefined)
}
globePhase={globePhase}
/>
</div>
</Resizable>
Expand Down
5 changes: 5 additions & 0 deletions src/store/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ import { atom } from 'recoil';
export const menuAtom = atom({
key: 'openedMenu',
default: false,
});

export const globePhaseAtom = atom({
key: 'globePhase',
default: 0,
});

0 comments on commit efb3bb3

Please sign in to comment.