From b0c67382ecb0d1273ce37e1693f957cbfab49d82 Mon Sep 17 00:00:00 2001 From: Jeran Date: Mon, 2 Mar 2026 14:58:03 +0100 Subject: [PATCH 1/2] Add axis bars --- src/GlobalStates/PlotStore.ts | 6 +- src/components/plots/Plot.tsx | 25 ++++++++- src/components/ui/Elements/AxisBars.tsx | 46 ++++++++++++++++ src/components/ui/Footer.tsx | 14 ++++- src/components/ui/NavBar/Navbar.tsx | 3 +- src/components/ui/css/AxisBars.css | 73 +++++++++++++++++++++++++ src/components/ui/index.ts | 1 + 7 files changed, 160 insertions(+), 8 deletions(-) create mode 100644 src/components/ui/Elements/AxisBars.tsx create mode 100644 src/components/ui/css/AxisBars.css diff --git a/src/GlobalStates/PlotStore.ts b/src/GlobalStates/PlotStore.ts index e11e4997..d88b2834 100644 --- a/src/GlobalStates/PlotStore.ts +++ b/src/GlobalStates/PlotStore.ts @@ -62,6 +62,7 @@ type PlotState ={ borderTexture: THREE.Texture | undefined; useBorderTexture: boolean; maskValue: number; + cameraPosition: THREE.Vector3; setQuality: (quality: number) => void; setTimeScale: (timeScale : number) =>void; @@ -116,6 +117,7 @@ type PlotState ={ setInterpPixels: (interpPixels: boolean) => void; setUseOrtho: (useOrtho: boolean) => void; setFillValue: (fillValue: number | undefined) => void; + setCameraPosition: (cameraPosition: THREE.Vector3) => void; } export const usePlotStore = create((set, get) => ({ @@ -180,6 +182,7 @@ export const usePlotStore = create((set, get) => ({ useBorderTexture: false, maskValue: 0, borderWidth: 0.05, + cameraPosition: new THREE.Vector3(0, 0, 5), setVTransferRange: (vTransferRange) => set({ vTransferRange }), setVTransferScale: (vTransferScale) => set({ vTransferScale }), @@ -235,5 +238,6 @@ export const usePlotStore = create((set, get) => ({ setXSlice: (xSlice) => set({ xSlice }), setInterpPixels: (interpPixels) => set({ interpPixels }), setUseOrtho: (useOrtho) => set({ useOrtho }), - setFillValue: (fillValue) => set({ fillValue }) + setFillValue: (fillValue) => set({ fillValue }), + setCameraPosition: (cameraPosition) => set({ cameraPosition }), })) \ No newline at end of file diff --git a/src/components/plots/Plot.tsx b/src/components/plots/Plot.tsx index 7c6f008e..0d4237aa 100644 --- a/src/components/plots/Plot.tsx +++ b/src/components/plots/Plot.tsx @@ -26,10 +26,11 @@ const TransectNotice = () =>{ } const Orbiter = ({isFlat} : {isFlat : boolean}) =>{ - const {resetCamera, useOrtho, displaceSurface} = usePlotStore(useShallow(state => ({ + const {resetCamera, useOrtho, displaceSurface, cameraPosition} = usePlotStore(useShallow(state => ({ resetCamera: state.resetCamera, useOrtho: state.useOrtho, - displaceSurface: state.displaceSurface + displaceSurface: state.displaceSurface, + cameraPosition:state.cameraPosition }))) const {setCameraRef} = useImageExportStore(useShallow(state=>({setCameraRef:state.setCameraRef}))) const orbitRef = useRef(null) @@ -78,7 +79,6 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{ return () => cancelAnimationFrame(frameId); } },[resetCamera, isFlat]) - useEffect(()=>{ if (hasMounted.current){ let newCamera; @@ -115,6 +115,25 @@ const Orbiter = ({isFlat} : {isFlat : boolean}) =>{ } },[useOrtho]) + useEffect(()=>{ + const cam = cameraRef.current + const controls = orbitRef.current + if (cam && controls){ + const wasDamping = controls.enableDamping; + controls.enableDamping = false; + controls.update() //Need this extra update to clear the internal inertia buffer. Cant seem to access it in code. + invalidate() + cam.position.copy(cameraPosition) + cam.lookAt(new THREE.Vector3(0, 0, 0)) + //@ts-ignore the check means it is ortho + if (useOrtho) cam.updateProjectionMatrix() + else cam.updateMatrix() + controls.update() + controls.enableDamping = wasDamping + invalidate() + } + },[cameraPosition]) + return ( { + const {setCameraPosition} = usePlotStore(useShallow(state =>({ + setCameraPosition: state.setCameraPosition + }))) + + return ( +
+
+ +
setCameraPosition(new THREE.Vector3(5, 0, 0))} + onDoubleClick={()=>setCameraPosition(new THREE.Vector3(-5, 0, 0))} + > +
+
+ X +
+ +
setCameraPosition(new THREE.Vector3(0, 5, 0))} + onDoubleClick={()=>setCameraPosition(new THREE.Vector3(0, -5, 0))} + > +
+
+ Y +
+ +
setCameraPosition(new THREE.Vector3(0, 0, 5))} + onDoubleClick={()=>setCameraPosition(new THREE.Vector3(0, 0, -5))} + > +
+
+ Z +
+
+ ) +} + + diff --git a/src/components/ui/Footer.tsx b/src/components/ui/Footer.tsx index 3e1f348c..aa417697 100644 --- a/src/components/ui/Footer.tsx +++ b/src/components/ui/Footer.tsx @@ -2,9 +2,17 @@ import Image from "next/image"; import { logoBGC_MPI, logoBGC, logoMPI } from "@/assets/index"; import './css/Footer.css'; +import { useImageExportStore } from "@/GlobalStates"; +import { useShallow } from "zustand/shallow"; -const Footer = () => ( -
+const Footer = () => { + const {previewExtent} = useImageExportStore(useShallow(state => ({ + previewExtent:state.previewExtent, + }))) + return( + -); +)} export default Footer; diff --git a/src/components/ui/NavBar/Navbar.tsx b/src/components/ui/NavBar/Navbar.tsx index ced1b0fc..d55fb7e6 100644 --- a/src/components/ui/NavBar/Navbar.tsx +++ b/src/components/ui/NavBar/Navbar.tsx @@ -10,7 +10,7 @@ import { useRef, useState } from "react"; import { MdFlipCameraIos } from "react-icons/md"; import { RiCloseLargeLine, RiMenu2Line } from "react-icons/ri"; import { useShallow } from "zustand/shallow"; -import { Button } from "@/components/ui/button"; +import { Button, AxisBars } from "@/components/ui"; import { Tooltip, TooltipContent, @@ -72,6 +72,7 @@ const Navbar = React.memo(function Navbar() {
{plotOn && ( <> +